2009-09-19 24 views
33

Lo siguiente funciona bien con tipos de IEnumerable, pero ¿hay alguna forma de que algo como esto funcione con tipos IQueryable en una base de datos sql?LINQ Between Operator

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

Respuesta

44

Si lo expresas como una cláusula where que puede simplemente trabajar fuera de la caja con LINQ a SQL, si se puede construir una expresión apropiada.

Puede haber una mejor forma de hacerlo en términos de árboles de expresión, Marc Gravell bien puede mejorarlo, pero vale la pena intentarlo.

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

es probable que dependerá del tipo implicado, aunque - en particular, he utilizado los operadores de comparación en lugar de IComparable<T>. Sospecho que es más probable que se traduzca correctamente en SQL, pero puede cambiarlo para usar el método CompareTo si lo desea.

invocarlo como esto:

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

Niza. Esto también me hizo entender las expresiones de Linq un poco más. – Dykam

+0

Jon, Lo siento, no he aceptado esto. Estado bajo el clima por unos días. Pregunta: usted escribe sobre el uso de operadores de comparación en lugar de IComparable . Como se veria eso? ¿Qué aspecto tendría esto como un IEnumerable ? Necesito jugar con esto y espero hacerlo hoy. ¡Muchas gracias! – andleer

+0

Usando 'IComparable ' necesitaría árboles de expresiones para invocar CompareTo dos veces. Todo factible, pero un poco doloroso. No estoy seguro de lo que quiere decir con "¿Qué aspecto tendría esto como un' IEnumerable '? " - ¿puedes elaborar? –