2017-09-21 8 views
0

EFで変数検索クエリを生成するシステムを作成しています。これを達成するために、私は動的にExpression<Func<T>>を構築します。式の評価値を選択する方法<Func<T>> Entity Frameworkクエリ

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); 
} 
//... 

は、その後、私はそうのように、このEF互換Expression<T>に私のクエリを注文します。

List<Entity> result; 
using (var context = new DatabaseContext()) 
    result = context.Table.OrderByDescending(matchScore).Take(MaxResults).ToList(); 

ここで問題となっているのは、注文の原因となったスコアがどのようなものかわかりません。私はこれをすることができるようにしたいと思います。

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(); 

もちろん、問題はy is Expression<T>で、これは無効です。私は.Select(matchScore)を使うことができましたが、元のエンティティを持っていません。

+0

は、私は見ての通り、 'matchScore'が一度初期化して、DBからデータを取得するまで変更されません。したがって、あなたは 'matchScore'をコンパイルし、返された関数をメモリからダウンロードされたdbから取得したデータに適用することができます。あなたはそれを試しましたか? –

答えて

1

あなたはこのようなLINQKitで式を組み合わせることができます

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 }; 

InvokeExpandAsExpandableの使用に注意してください。 デモ:

demo

関連する問題