2009-02-20 21 views
11

私は、さまざまなWhereWhereBetweenのステートメントを使用して特定のセットに絞ったクエリ可能なを持っています。今私はWhere || WhereBetweenの種類を追加する必要があります。言い換えれば、私は今までのようにそれらを連鎖させることはできません。なぜならそれはAndとして機能するからです。では、どうしたらいいですか?私が持っている1から2 queryables、WhereBetweenを使用してWhere、および1を使用して作成C#、Linq2Sql:2つのクエリ可能なものを連結することは可能ですか?

  1. は、私は2つの可能性を参照してください。 そして、それらを連結する。これが可能なのかどうかわからない?また、私の特定のケースではないが、あなたが最も可能性が高い

  2. はどういうわけかWhere表現とOrのいくつかの並べ替えとWhereBetweenで作成された表現をマージ...重複で終わるでしょう。

まず、前述したように、私も可能であることを確認していません。それがあれば、私はそれが良い方法であるとは確信していません。

秒、私はオプションとして見ますが、すべての詳細については全くわからないことができます。以下は、私が今使用して、私の他の質問からWhereBetween方法であり、それは素晴らしい作品:私は多分新しい方法にそれの発現建物部分を抽出できると思ってい

public static IQueryable<TSource> WhereBetween<TSource, TValue>(
     this IQueryable<TSource> source, 
     Expression<Func<TSource, TValue>> selector, 
     IEnumerable<Range<TValue>> ranges) 
    { 
     var param = Expression.Parameter(typeof(TSource), "x"); 
     var member = Expression.Invoke(selector, param); 
     Expression body = null; 
     foreach (var range in ranges) 
     { 
      var filter = Expression.AndAlso(
       Expression.GreaterThanOrEqual(member, 
        Expression.Constant(range.A, typeof(TValue))), 
       Expression.LessThanOrEqual(member, 
        Expression.Constant(range.B, typeof(TValue)))); 
      body = body == null ? filter : Expression.OrElse(body, filter); 
     } 
     return body == null ? source : source.Where(
      Expression.Lambda<Func<TSource, bool>>(body, param)); 
    } 

。おそらく、次のようになります。

public static IQueryable<TSource> WhereBetween<TSource, TValue>(
     this IQueryable<TSource> source, 
     Expression<Func<TSource, TValue>> selector, 
     IEnumerable<Range<TValue>> ranges) 
    { 
     return source.Where(WhereBetween(selector, ranges)); 
    } 

    public static Expression<Func<TSource, bool>> WhereBetween<TSource, TValue>(
     Expression<Func<TSource, TValue>> selector, 
     IEnumerable<Range<TValue>> ranges) 
    { 
     var param = Expression.Parameter(typeof(TSource), "x"); 
     var member = Expression.Invoke(selector, param); 
     Expression body = null; 
     foreach (var range in ranges) 
     { 
      var filter = Expression.AndAlso(
       Expression.GreaterThanOrEqual(member, 
        Expression.Constant(range.A, typeof(TValue))), 
       Expression.LessThanOrEqual(member, 
        Expression.Constant(range.B, typeof(TValue)))); 
      body = body == null ? filter : Expression.OrElse(body, filter); 
     } 
     return body == null 
      ? ø => true 
      : Expression.Lambda<Func<TSource, bool>>(body, param); 
    } 

私はこの新しいメソッドを使用して、クエリ可能ではなく式を取得できました。だから、WhereBetween(ø => ø.Id, someRange)があり、たとえばø => ø.SomeValue == nullと言うことができます。これらの2つをOrと組み合わせるにはどうすればよいですか?私はWhereBetween方法で使用されるExpression.OrElseを見ている、と私はそれは私が必要なものかもしれないと思う、または多分このExpression.Or。しかし、私は、この式のものに非常に不安定なので、私はここで選択するのか、または私は正しい軌道に乗っていても、わからない:P

誰かがここに私にいくつかのポインタを与えることができますか? Queryable.Union、または発現の組み合わせ -

答えて

9

次の2つのここでのオプションがあります。 (下記参照)を使用すると、2式を行うことができます(LINQツーSQL少なくとも付き) - - 私は一般的にOrElseを経由して、後者を好むだろうが、いずれの場合も、それは構成を取得する必要があります

using(var ctx = new DataClasses1DataContext()) 
    { 
     ctx.Log = Console.Out; 
     Expression<Func<Customer, bool>> lhs = 
      x => x.Country == "UK"; 
     Expression<Func<Customer, bool>> rhs = 
      x => x.ContactName.StartsWith("A"); 

     var arr1 = ctx.Customers.Where(
      lhs.OrElse(rhs)).ToArray(); 

     var arr2 = ctx.Customers.Where(lhs) 
      .Union(ctx.Customers.Where(rhs)).ToArray(); 
    } 

両方を(TSQLが異なるが、最初はWHERE句でORを有し、第二はUNIONを持つ2つの別個のクエリを持っている)arr1arr2それぞれ1本のだけデータベースヒットを実行します。

ここで私が使用する拡張メソッドです:

static Expression<Func<T, bool>> OrElse<T>(
    this Expression<Func<T, bool>> lhs, 
    Expression<Func<T, bool>> rhs) 
{ 
    var row = Expression.Parameter(typeof(T), "row"); 
    var body = Expression.OrElse(
     Expression.Invoke(lhs, row), 
     Expression.Invoke(rhs, row)); 
    return Expression.Lambda<Func<T, bool>>(body, row); 
} 
+0

は、その行の事は何でも右のだろうか?(任意の文字列はもちろんです) – Svish

+0

SQLのパフォーマンスなどを考えれば、WHERE節にある 'UNION'や' OR'を使う方が効率的ですか? – Svish

+0

非常に良い。この質問は引き続き(バリエーションで)登場し、OrElseはそれらをすべて解決する魔法の弾丸かもしれません。 –

関連する問題