2009-11-02 25 views
7

ho una query LINQ che sembra qualcosa di simile:Linq: semplice funzione booleana restituisce LINQ Eccezione

var query = from x in table where SomeFunctionReturnsBool() select; 

private bool SomeFunctionReturnsBool() 
{ 
    return true; 
} 

Ciò restituisce e eccezione che dice "SomeFunctionReturnsBool non ha alcuna traduzione supportato per SQL". Ho capito che questo è perché vuole trattare "SomeFunctionReturnsBool" come espressione da valutare come SQL, ma non può.

Sebbene questa query di Linq non sia complicata, quelle reali lo sono. Come posso realizzare ciò che sto cercando di fare qui, che è quello di scomporre parti della query per renderlo più leggibile?

Jeff

UPDATE buone risposte. Sto cercando ora di lavorare con le espressioni, invece, ma questo codice mi colpisce "non può risolvere il metodo Dove (espressione lambda)":

var query = from x in table where SomeFunctionReturnsBool() select x; 

private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool 
{ 
    return (x) => true; 
} 
+0

risposto al commento, che mostra un modo (dubbia) di utilizzare questo approccio con sintassi di query. –

risposta

7

Un altro modo è quello di utilizzare Expression<Func<YourType, bool>> predicato ...

var query = from x in table where SomeFunctionReturnsBool() select; 

Edit: Io di solito non lo faccio il modo in cui ho mostrato sopra ... Stavo solo ottenere che dal codice sopra. Ecco come di solito lo implemento. Perché in questo modo è possibile utilizzare metodi Enumerable aggiuntivi o commentarli durante il debug.

var results = table.Where(SomeFunctionReturnsBool()) 
    .OrderBy(yt => yt.YourProperty) 
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts... 
    //.Take(pageSize) 
    .ToList(); //Finally executes the query... 

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool() 
{ 
    return (YourType yt) => yt.YourProperty.StartsWith("a") 
     && yt.YourOtherProperty == true; 
} 

io preferisco usare il PredicateBuilder, che permette di costruire un'espressione da utilizzare nel vostro Dove ...

+1

+1 per PredicateBuilder. E 'carino – Tinister

+0

Per qualche ragione, fare questo causa il dove per errore con "non è possibile risolvere il metodo dove (espressione lambda)" – jlembke

+0

Non sono sicuro del motivo per cui ho ottenuto -2 essere bello se avessi "tempo" per spiegare il tuo voto negativo ... – bytebender

3

è possibile farlo in LINQ to SQL con la creazione di una funzione definita dall'utente associato al contesto dati; questo implica scrivere TSQL e usare ctx.SomeFunctionblah (...).

L'alternativa è quella di lavorare con gli alberi di espressione - ad esempio, potrebbe essere:

Expression<Func<Customer, bool>> SomeFunc() { 
    return c => true; // or whatever 
} 

e utilizzare .Where(SomeFunc()) - è che abbastanza vicino? Non è possibile utilizzare la sintassi di query in questo caso, ma ottiene il lavoro fatto ...


Aggiunto dodgy Where metodo per mostrare come si potrebbe utilizzarlo nella sintassi di query. I non suggerisco questo è fantastico, ma potresti trovarlo utile.

using System; 
using System.Linq; 
using System.Linq.Expressions; 

static class Program 
{ 
    static void Main() 
    { 
     using (var ctx = new NorthwindDataContext()) 
     { 
      ctx.Log = Console.Out; 
      // fluent API 
      var qry = ctx.Customers.Where(SomeFunc("a")); 
      Console.WriteLine(qry.Count()); 

      // custom Where - purely for illustration 
      qry = from c in ctx.Customers 
        where SomeFunc("a") 
        select c; 
      Console.WriteLine(qry.Count()); 
     } 
    } 
    static IQueryable<T> Where<T>(this IQueryable<T> query, 
     Func<T, Expression<Func<T, bool>>> predicate) 
    { 
     if(predicate==null) throw new ArgumentNullException("predicate"); 
     return query.Where(predicate(default(T))); 
    } 
    static Expression<Func<Customer, bool>> SomeFunc(string arg) 
    { 
     return c => c.CompanyName.Contains(arg); 
    } 
} 
+0

wow, figo Marc, non lo sapevo. Controlla la mia risposta qui sotto ... è utile, ma è molto bello. grazie – andy

+0

Giusto per chiarire, Marc. Se uso l'albero delle espressioni come lo hai qui, devo usare la sintassi lambda e non la sintassi delle query? – jlembke

+0

Bello. Ok, lavorerò con quello. – jlembke

0

Non utilizzare la sintassi di query per questo.

var query = table.Where(x => SomeFunction(x)); 
+0

Ciò non aiuterà con LINQ-to-SQL; non c'è ancora nessuna traduzione per 'SomeFunction'. –

+0

sì, non c'è differenza tra questo e la sintassi della query – andy

+0

sì, questo è lo stesso .. – jlembke

1

avrei semplicemente uscire in questo modo:

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true; 

var query = from x in table where someTreeThatReturnsBool select x; 

Si potrebbe creare funzioni che passano attorno agli alberi di espressione.

2

Fondamentalmente, "out of the box", non è possibile eseguire query LINQ-to-SQL che contengono funzioni personalizzate. Infatti, solo alcuni metodi nativi che possono essere tradotti in SQL possono essere utilizzati.

Il modo più semplice per aggirare questo può sfavorevolmente influenzare le prestazioni a seconda della quantità di dati che si sta richiamando dal DB.

Fondamentalmente, è possibile utilizzare le funzioni personalizzate nelle istruzioni WHERE solo se i dati sono già stati caricati in memoria, vale a dire, SQL è già stato eseguito.

La soluzione più rapida per il tuo esempio sarebbe simile a questa:

var query = from x in table.ToList() where SomeFunctionReturnsBool() select; 

Avviso del ToList(). Esegue l'SQL e mette i dati in memoria. Ora puoi fare tutto ciò che vuoi nel WHERE statement/method.

+2

Vero ... ma poi si stanno ritirando tutti i record e poi si fa il filtraggio in memoria rispetto a fare sul server database . – bytebender

+0

Concordato (con J.13.L) - l'uso di 'ToList()' è in genere un cattivo modo per farlo, e funziona solo con piccoli volumi di dati. –

+0

Mi piacerebbe molto evitarlo. Un sacco di dati. Grazie Andy, concordato – jlembke