0

Linq To Entities を使用してアプリをパワーアップしていますが、非常に複雑な検索クエリを作成したいと考えています...必要なものを確認してください:

ユーザーが "Washington Boston" のような文字列を入力すると、" " (空のスペース、この場合は 2 つの文字列) の量に応じて N 個の文字列に分割し、Counties テーブルで Washington と Boston を検索します。

これが「静的な」クエリである場合、次のように記述します。where county.Name.Contains("Washington") || county.Name.Contains("Boston")しかし、ユーザーが入力する都市の数 (またはこの問題の空白) はわかりません...

古典的な純粋な TSQL 環境では、実行時にクエリをコンパイルし、コマンド Exec を使用します...だから私の質問は次のとおりです: LINQ to entities クエリを動的に生成する方法は?

.Where() は、デリゲートに基づく拡張メソッドではないことに注意してください...バックエンドで TSQL に変換されません。つまり、バックエンドでfrom e in context.Counties.Where(c => c.Name.Contains("boston"))変換さSELECT ID,NAME FROM COUNTIESれます。

4

3 に答える 3

5

要件を達成する最も簡単な方法であるため、David Khaykinのコメントを回答に拡張します。

検索用語を用語のリストに分割し、要件に応じcountiesた方法を使用してエンティティをフィルタリングするだけです。Contains

var terms = searchTerm.Split(' ').ToList();

// an exact match  
counties.Where(c => terms.Contains(c.Name))

// a 'contains' or 'like' type match
counties.Where(c => terms.Any(t => c.Contains(t));

ContainsメソッドはSystem.Linq.Enumerable.Containsであり、ではありませんString.Contains

複雑な動的 LINQ クエリを作成する場合は、bmused で概説されている非常に強力なメソッドを使用できます。ただし、このタイプの単純なフィルタリングでは、ストレート リストを渡すことができます。

于 2013-03-13T01:58:43.960 に答える
2

System.Linq.Expressionsを使用できます

したがって、次のようなことを行います(テストされていません):

public Expression<Func<County, Boolean>> GetPredicate(List<String> terms)
{
//The string method - Contains
MethodInfo mContains = typeof(String).GetMethod("Contains");

//The parameter - county
ParameterExpression pe = Expression.Parameter(typeof(County), "County");

//The property - Name
Expression property = Expression.Property(pe, "Name");

//expression body
Expression body = null;

foreach(String term in terms)
{
  //the constant to look for
  Expression searchTerm = Expression.Constant(term);

   //build expression body
   if(body == null) body = Expression.Call(property, mContains, searchTerm);
   else body = Expression.OrElse(body, 
       Expression.Call(property, mContains, searchTerm));
}

//create predicate
return Expression.Lambda<Func<County, Boolean>>(body, pe);
}
于 2013-03-13T01:37:43.433 に答える
2

Predicate builder (およびEntity Framework を使用しているためLINQKit ) を使用すると、次のことが可能になります。

IQueryable<County> SearchInCountyNames(params string[] countyNames)
{
  var predicate = PredicateBuilder.False<County>();

  foreach (string countyName in countyNames)
  {
    string name = countyName;
    predicate = predicate.Or(c => c.Name.Contains(name));
  }


  return dataContext.Counties.AsExpandable().Where(predicate);
}

述語ビルダーのサイトには、さらに多くの例があります。

于 2013-03-13T01:39:57.443 に答える