2017-09-21 2 views
0

Je crée un système pour générer des requêtes de recherche de variables dans EF. Pour ce faire, je construis de manière dynamique un Expression<Func<T>> comme ça.Comment sélectionner la valeur d'expression évaluée <Func<T>> Dans Entity Framework Query

Expression<Func<Entity, float>> matchScore = x => 0; 
if (!string.IsNullOrWhiteSpace(NameLTB.Value)) 
{ 
    var words = NameLTB.Value.Split(' ').ToArray(); 
    var perWordValue = 2f/words.Length; 
    foreach (var word in words) 
     matchScore = ExpressionExt.Compose(matchScore, x => x.Name.Contains(word) ? perWordValue : 0f, Expression.Add); 
} 
//... 

Puis-je commander ma requête sur cette EF compatible Expression<T> comme si. Le problème ici est que je ne connais pas le score qui a provoqué l'ordre de l'ordre. J'aimerais pouvoir le faire.

List<Entity> result; 
using (var context = new DatabaseContext()) 
    result = 
     (
      from x in context.Table 
      let y = matchScore 
      orderby y descending 
      select new { Entity = x, MatchScore = y } 
     ) 
     .ToList(); 

Bien sûr, la question ici est y is Expression<T> qui n'est pas valide. Je pourrais utiliser .Select(matchScore) mais je n'ai pas l'entité d'origine pour l'accompagner.

+0

Comme je vois 'matchScore' initialize à la fois et ne change pas jusqu'à ce que vous récupérer des données de db. Vous pouvez donc compiler 'matchScore' et appliquer la fonction retournée aux données récupérées depuis la base de données qui ont été téléchargées dans la mémoire. L'as tu essayé? –

Répondre

1

Vous pouvez combiner les expressions avec LINQKit comme ceci:

Expression<Func<Entity, float>> matchScore = x => 0; 
Expression<Func<Entity, float>> matchScoreInc; 
string s = "a b"; 
if (!string.IsNullOrWhiteSpace(s)) 
{ 
    var words = s.Split(' ').ToArray(); 
    var perWordValue = 2f/words.Length; 
    foreach (var word in words) 
    { 
     matchScoreInc = x => matchScore.Invoke(x) + (x.Name.Contains(word) ? perWordValue : 0f); 
     matchScore = matchScoreInc.Expand(); 
    } 
} 

var q = 
    from x in table.AsExpandable() 
    let y = matchScore.Invoke(x) 
    orderby y descending 
    select new { Entity = x, MatchScore = y }; 

Notez l'utilisation de Invoke, Expand et AsExpandable. Démo:

demo