2009-06-12 17 views
17

Me gusta reutilizar expresiones por razones DRY, pero ¿cómo reutilizo las expresiones dentro de una declaración LINQ?¿Cómo puedo reutilizar expresiones dentro de las declaraciones LINQ?

p. Ej.

tengo

public static class MyExpressions { 
    public static Expression<Func<Product,bool>> IsAGoodProduct() { 
     return (p) => p.Quality>3; 
    } 
} 

Y me gustaría usar que en los estados de LINQ, por lo

var goodProds = from p in dataContext.Products 
        where ????? // how do I use IsAGoodProduct here? 
        select p; 

Claro, podría utilizar la función IQueryableExtension.Where, pero que haría que se une y otras funciones mucho más feo para consultas más complejas.

¿Esto es posible o es una limitación de LINQ?

Respuesta

21

Si se mueve desde el azúcar sintáctica LINQ es posible:

var goodProds = dataContext.Products.Where(MyExpressions.IsAGoodProduct()); 

Sin ella, no es posible.

Sin embargo, no hay nada que le impida mezclar los dos estilos para crear una sola consulta.

Ejemplo:

var goodProds = from p in dataContext.Products 
             .Where(MyExpressions.IsAGoodProduct()) 
        group p by p.Category into g 
        select new {Category = g.Key, ProductCount = g.Group.Count()}; 
+1

@Gary - espero que no te importe que agregué un ejemplo para hacerlo más claro. – tvanfosson

+0

No, eso es genial :) –

+0

¿Qué pasa con el uso: "donde IsAGoodProduct(). Compile(). Invoke()" – Razzie

1

Por cierto, me he encontrado con este useful article que explica cómo se puede crear consultas LINQ dinámicas que las funciones de referencia envueltos como expresiones usando un método de extensión personalizada ToExpandable(). La solución provista se puede usar dentro de las diversas partes de una consulta LINQ mientras se preserva el uso de comprehension syntax en lugar de recurrir a la sintaxis lambda.

2

Tuvimos el mismo problema. No es compatible desde el primer momento y es un problema importante para las aplicaciones de LOB. Terminé escribiendo un artículo sobre el proyecto de código sobre reutilización de expresiones LINQ, que incluye una utilidad muy pequeña llamada LinqExpressionPrjection que permite la reutilización en proyecciones (incluso en tipos anónimos).

Encuentra el artículo here.

Puede obtener el conjunto para la reutilización de proyección como nuget package y la fuente está en CodePlex.

Ha pasado algún tiempo desde su publicación. Espero que aún sea útil para ti. Si no, tal vez para otros que leen este hilo.

3

Tuve el mismo problema y quería preservar la capacidad de usar métodos de extensión dentro de la sintaxis de la consulta (como con las funciones comunes soportadas ...). Una solución podría ser this library.

Acaba de implementar el método para reutilizar dos veces, una para uso general y otra para consultas.

public static class MyFunctions { 
    [InjectLambda] 
    public static bool IsAGoodProduct(Product product) { 
     return product.Quality>3; 
    } 
    public static Expression<Func<Product,bool>> IsAGoodProduct() { 
     return (p) => p.Quality>3; 
    } 
} 

La consulta real puede verse como se esperaba.

var goodProds = from p in dataContext.Products.ToInjectable() 
       where p.IsAGoodProduct() 
       select p; 

La llamada ToInjectable crea un proxy de peso ligero, que sustituye a la llamada IsAGoodProduct método (si está marcado en consecuencia) con la expresión lambda deseada.Por lo tanto, puede usar métodos de extensión en cualquier lugar de la consulta; los métodos parametrizados también funcionan.

Cuestiones relacionadas