2009-09-19 33 views
33

Sau đây hoạt động tốt với các loại IEnumerable, nhưng có cách nào để có được một cái gì đó như thế này làm việc với các loại IQueryable đối với một cơ sở dữ liệu sql?LINQ giữa nhà điều hành

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

Trả lời

44

Nếu bạn thể hiện nó như một điều khoản wherethể chỉ làm việc ra khỏi hộp với LINQ to SQL, nếu bạn có thể xây dựng một biểu thức thích hợp.

Có thể có cách tốt hơn để thực hiện việc này về cây biểu thức - Marc Gravell cũng có thể cải thiện nó - nhưng đáng để thử.

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

Nó có thể phụ thuộc vào loại liên quan - đặc biệt, tôi đã sử dụng toán tử so sánh thay vì IComparable<T>. Tôi nghi ngờ điều này có nhiều khả năng được dịch chính xác sang SQL, nhưng bạn có thể thay đổi nó để sử dụng phương thức CompareTo nếu bạn muốn.

Gọi nó như thế này:

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

Nice. Điều này cũng khiến tôi hiểu biểu thức của Linq nhiều hơn một chút. – Dykam

+0

Jon, Rất tiếc, tôi chưa chấp nhận điều này. Đã được thời tiết trong một vài ngày. Câu hỏi: bạn viết về cách sử dụng toán tử so sánh thay vì IComparable . Nó sẽ trông như thế nào? Điều gì sẽ trông giống như một số điện thoại IEcủa IEnumerable? Tôi cần phải chơi với điều này và hy vọng sẽ làm điều đó ngày hôm nay. Cảm ơn nhiều! – andleer

+0

Sử dụng 'IComparable ' bạn cần các cây biểu thức để gọi CompareTo hai lần. Tất cả đều có thể làm được, nhưng hơi đau. Không chắc chắn ý của bạn về "Cái gì sẽ trông giống như một 'IEnumerable '? " - bạn có thể xây dựng? –