2009-09-19 16 views
33

次はIEnumerable型でうまく動作しますが、SQLデータベースに対してIQueryable型を使用しているようなものを得る方法はありますか?LINQ演算子間

class Program 
{ 
    static void Main(string[] args) 
    { 
     var items = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }; 

     foreach (var item in items.Where(i => i.Between(2, 6))) 
      Console.WriteLine(item); 
    } 
} 

static class Ext 
{ 
    public static bool Between<T>(this T source, T low, T high) where T : IComparable 
    { 
     return source.CompareTo(low) >= 0 && source.CompareTo(high) <= 0; 
    } 
} 

答えて

44

あなたが適切な表現を構築することができれば、それはだけで、SQLにLINQと箱から出して動作することがありwhere句としてそれを表現した場合。

これは表現木の点でより良い方法かもしれません - Marc Gravellはそれを改善することはできますが、試してみる価値があります。

static class Ext 
{ 
    public static IQueryable<TSource> Between<TSource, TKey> 
     (this IQueryable<TSource> source, 
     Expression<Func<TSource, TKey>> keySelector, 
     TKey low, TKey high) where TKey : IComparable<TKey> 
    { 
     Expression key = Expression.Invoke(keySelector, 
      keySelector.Parameters.ToArray()); 
     Expression lowerBound = Expression.GreaterThanOrEqual 
      (key, Expression.Constant(low)); 
     Expression upperBound = Expression.LessThanOrEqual 
      (key, Expression.Constant(high)); 
     Expression and = Expression.AndAlso(lowerBound, upperBound); 
     Expression<Func<TSource, bool>> lambda = 
      Expression.Lambda<Func<TSource, bool>>(and, keySelector.Parameters); 
     return source.Where(lambda); 
    } 
} 

これはおそらく、しかし、関係タイプに依存します - 特に、私はむしろIComparable<T>よりも、比較演算子を使用しました。これはSQLに正しく変換される可能性が高いと思われますが、必要に応じてCompareToメソッドを使用するように変更できます。

var query = db.People.Between(person => person.Age, 18, 21); 
+0

ニース:

はこのようにそれを呼び出します。これによりLinqの表現がもう少し分かりました。 – Dykam

+0

Jon、 申し訳ありませんが、私はこれを受け入れていません。天気の下で数日間されています。質問:IComparable の代わりに比較演算子を使うことについて書いています。どのように見えるだろうか?これはIEnumerable のように見えますか?私はこれと遊ぶ必要があり、今日それを行うことを望む。どうもありがとう! – andleer

+0

'IComparable 'を使うと、CompareToを2回呼び出す式ツリーが必要になります。すべての可能な、しかし少し痛み。 "IEnumerable 'のように見えるものは何でしょうか? - あなたは精巧にできますか? –