2009-06-12 10 views
17

Mi piace riutilizzare le espressioni per motivi di DRY, ma come posso riutilizzare le espressioni all'interno di un'istruzione LINQ?Come posso riutilizzare le espressioni all'interno delle istruzioni LINQ?

ad es.

ho

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

E vorrei utilizzare che nelle dichiarazioni LINQ, quindi

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

Certo, avrei potuto utilizzare la funzione IQueryableExtension.Where, ma che renderebbero unisce e altre funzioni molto più brutto per query più complesse.

È possibile o si tratta di un limite di LINQ?

risposta

21

Se si sposta dalla zucchero sintattico LINQ è possibile:

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

Senza di essa, non è possibile.

Non c'è niente che impedisca di mescolare i due stili per creare una singola query.

Esempio:

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 - spero che non ti dispiaccia che ho aggiunto un esempio per renderlo più chiaro. – tvanfosson

+0

No, è grandioso :) –

+0

Che dire di usare: "dove IsAGoodProduct(). Compila(). Invoke()" – Razzie

1

A proposito, ho incontrato questa useful article che spiega come è possibile creare dinamiche LINQ query che funzioni di riferimento avvolto come espressioni utilizzando un metodo di estensione personalizzata ToExpandable(). La soluzione fornita può essere utilizzata all'interno delle varie parti di una query LINQ, pur preservando l'uso di comprehension syntax anziché ricorrere alla sintassi lambda.

2

Abbiamo avuto lo stesso problema. Non è supportato immediatamente ed è un grosso problema per le applicazioni LOB. Ho finito per scrivere un articolo sul progetto di codice sul riutilizzo delle espressioni LINQ, inclusa una piccola utility chiamata LinqExpressionPrjection che consente il riutilizzo nelle proiezioni (anche in tipi anonimi).

Trova l'articolo here.

È possibile ottenere il gruppo per il riutilizzo di proiezione come nuget package e la sorgente è CodePlex.

Qualche tempo è passato dal tuo post. Spero che sia ancora utile per te. In caso contrario, forse per gli altri a leggere questa discussione.

3

Ho avuto lo stesso problema e volevo conservare la possibilità di utilizzare i metodi di estensione all'interno della sintassi della query (come con le normali funzioni supportate ...). Una soluzione potrebbe essere this library.

Basta implementare il metodo per riutilizzare due volte, una volta per l'uso generale e una volta per le query.

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 query effettiva può quindi apparire come prevista.

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

Il ToInjectable crea di un proxy leggero, che sostituisce la chiamata IsAGoodProduct metodo (se marcati conseguenza) con l'espressione lambda desiderata.Pertanto, è possibile utilizzare i metodi di estensione ovunque all'interno della query - funzionano anche i metodi parametrizzati.

Problemi correlati