2015-12-17 14 views
29

Es geht nicht um die Wiederverwendung eines Ergebnisses, sondern um die Anweisung selbst. Noch ist es über einen Fehler bei der Verwendung von var wie erwähnt in: LINQ to SQL: Reuse lambda expressionWiederverwendung einer LINQ-Abfrage

Aus reiner Neugier habe ich mich gefragt, ob es möglich ist, eine einzelne LINQ-Anweisung zu verwenden.

Lets sagen, dass ich die folgende LINQ-Anweisung haben:

.Where(x => x.Contains("")); 

Ist es möglich, die Anweisung x => x.Contains("") und verwenden eine Art von Hinweis auf diese für die spätere Verwendung in, extrahieren können sagen, eine andere Klasse?

So kann ich es nennen mag: .Where(previouslySavedStatement);

+5

setzen Sie es in eine Variable. 'Func func = x => x.enthält (" ");' –

+3

@wudzik Dies ist kein Duplikat. Die doppelte Referenz bezieht sich auf die Wiederverwendung von Ergebnissen, die Frage fragt nach der Wiederverwendung der Abfrage selbst. – Shlomo

+0

Danke Shlomo :) gerade die Bearbeitung selbst – Blaatz0r

Antwort

35

Sie es in einer Variablen speichern kann. Wenn Sie mit IQueryable arbeiten dann verwenden:

System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains(""); 

Wenn Sie IEnumerable verwenden, dann verwenden:

Func<Foo, bool> selector = x => x.Contains(""); 

und verwenden Sie es in Ihrer Anfrage:

query.Where(selector); 
+6

FYI zu @ Blaatz0r Wenn Sie mit einem '' IEnumerable anstelle eines 'IQueryable ' arbeiten würden Sie nur 'Func Selektor = ...', aber wenn Sie mit 'IQueryable ' Sie am meisten wollen trotzig Verwenden Sie die 'Expression >' Version. –

+1

@ScottChamberlain Die meisten meiner Aussagen sind IEnumerable so danke für die Köpfe – Blaatz0r

+1

@ Blaatz0r, wenn Sie die Expression-Version haben, können Sie es auch in einen Delegaten konvertieren, indem Sie tun 'Func selector2 = selector.Compile();', Sie kann nicht die andere Richtung von einem Delegaten zu einem Ausdruck gehen. –

5

Es hängt davon ab. Es gibt zwei Methoden: Where, Enumerable.Where und Queryable.Where. Wenn Sie die .Where auf eine IEnumerable anwenden, als die erste aufgerufen wird, wenn Sie es auf eine IQueryable anwenden, wird die zweite aufgerufen.

Da Enumerable.Where eine Func einnimmt, ist es nicht wiederverwendbar. Da Queryable.Where einen Ausdruck einnimmt, ist es wiederverwendbar. Sie können dies tun, wie folgt:

var x = new List<string>().AsQueryable(); 

var query = x.Where (n => n.Contains("some string")); 

//Extract the lambda clause 
var expr = query.Expression; 
var methodExpr = (MethodCallExpression)expr; 
var quoteExpr = (UnaryExpression)methodExpr.Arguments[1]; 
var funcExpr = (Expression<Func<string, bool>>)quoteExpr.Operand; 

Sie können dann später erneut anwenden, die in dem Ausdruck:

var query2 = x.Where(funcExpr); 
+1

Haben Sie die angenommene Antwort gelesen? – CSharpie

+2

Ja, ich habe sogar die angenommene Antwort gelesen, und ich habe sogar die Frage gelesen. Ich glaube sogar, dass meine Antwort die Frage beantwortet, die sogar besser gestellt wurde als die angenommene Antwort. – Shlomo

8

Ja, können Sie eine Funktion, welche die Abfrage, die Sie wiederverwenden möchten schreiben, das dauert und ein IQueryable < T zurück >

public IQueryable<T> ContainsEmpty(IQueryable<T> query) 
    { 
     return query.Where(x => x.Contains("")); 
    } 

Jetzt können Sie es wiederverwenden:

query1 = ContainsEmpty(query1); 
    query2 = ContainsEmpty(another); 
+0

+1 Dies beantwortet nicht direkt die Frage von OP, aber es ist ein viel besserer Weg, sein Problem zu lösen _ (obwohl, warum haben Sie 'IQueryable ' anstelle von 'IEnumerable ' '?) _ –

+1

Der Datentyp ist nicht in angegeben die Frage, aber es erwähnt "LINQ to SQL" und hat "query" im Titel, so vermutete ich IQueryable :-) – buffjape