2014-06-12 3 views
5

Ich versuche, dynamische Abfragen für das Entity-Framework (oder einen anderen Linq-Provider) zu erstellen.So deklarieren Sie eine Linq-Expression-Variable, damit sie als dbParameter verarbeitet werden kann

Lassen Sie mich mein Problem mit einem Beispielcode erklären.

Wenn ich hart codieren einen Ausdruck:

var id = 12345; 

Expression<Func<ItemSearch, bool>> myLambda = (s) => s.Id == id; 

var finalQuery = context.ItemSearch.Where(myLambda); 
this.Log((finalQuery as ObjectQuery).ToTraceString()); 

Die generierten SQL wie folgt aussieht:

SELECT ... 
FROM ViewItemSearch "Extent1" 
WHERE "Extent1".ID = :p__linq__0 

mit einem schönen :p__linq__0 DbParameter.

Wenn ich erstellen einen Ausdruck:

var id = 12345; 
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s"); 
Expression prop = Expression.Property(param, "Id"); 
Expression val = Expression.Constant(id); 
Expression searchExpr = Expression.Equal(prop, val); 

Expression<Func<ItemSearch, bool>> myLambda = 
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr , param); 

var finalQuery = context.ItemSearch.Where(myLambda); 
this.Log((finalQuery as ObjectQuery).ToTraceString()); 

Die generierten SQL wie folgt aussieht:

SELECT ... 
FROM ViewItemSearch "Extent1" 
WHERE "Extent1".ID = 12345 

nicht mehr :p__linq__0 DbParameter so die DB-Engine kann nicht Cache-Abfragepläne.

Ich verstehe, dass es ist, weil ich

Expression val = Expression.Constant(id); 

benutzen, aber ich kann nicht herausfinden, wie eine Variable zu binden, anstelle des Wertes.

+0

Ich finde Ihre Frage ist etwas verwirrend. Wenn Sie logische UND-Bedingungen dynamisch hinzufügen möchten, deklarieren Sie einfach ein "IQueryable" und fügen Sie ".Where (i => yourPredicate)" dynamisch hinzu. Siehe: http://stackoverflow.com/questions/11189826/c-sharp-dynamic-linq-variable-where-clause Wenn Sie "OR" Logik anwenden möchten, benötigen Sie einen Ansatz wie folgt: http : //www.albahari.com/nutshell/predicatebuilder.aspx – andleer

+0

Die 'oder' und 'und' Ausdrücke funktionieren gut. Das Problem liegt in der Bindung von Parametern. Vielleicht sollte ich die Frage bearbeiten und das Ende entfernen. Was nur für den Kontext ist. –

Antwort

7

Sie müssen eine Lambda bei der Kompilierung erstellen, um zu schließen über die id Variable, auf die Sie dann den Körper eines in der Zusammensetzung Ihrer komplexeren Lambda Verwendung greifen:

var id = 12345; 
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s"); 
Expression prop = Expression.Property(param, "Id"); 
Expression<Func<int>> idLambda =() => id; 
Expression searchExpr = Expression.Equal(prop, idLambda.Body); 

Expression<Func<ItemSearch, bool>> myLambda = 
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr, param); 
Verwandte Themen