Ich habe eine Liste von Listen der Bedingungen, die vom Client gesendet werden. Ich muss diese Liste nehmen und eine dynamische where-Klausel erstellen, die von EntityFramework ausgeführt wird.Ausdrucksbaum zum Erstellen von dynamischen Where-Klausel werfen Fehler im Zusammenhang mit Parametern
Jede Bedingung hat einen Operator, ein Attribut und einen Wert auf der rechten Seite.
Jede Liste von Bedingungen muss ANDed zusammen sein.
Jede Liste von Bedingungen muss OR-verknüpft werden.
Also, wenn wir hatten
{
"ConditionLists":[
[
{
"LhsAttributeDefinition":{
"attribute":{
"key":"isHighBandwidth",
"value":"IsHighBandwidth"
}
},
"Operator":{
"name":"equals",
"description":"=",
"validation":"",
"inputType":"dropdown"
},
"RhsValue":"true"
},
{
"LhsAttributeDefinition":{
"attribute":{
"key":"isForMobile",
"value":"IsForMobile"
}
},
"Operator":{
"name":"equals",
"description":"=",
"validation":"",
"inputType":"dropdown"
},
"RhsValue":"true"
}
],
[
{
"LhsAttributeDefinition":{
"attribute":{
"key":"isHighBandwidth",
"value":"IsHighBandwidth"
}
},
"Operator":{
"name":"equals",
"description":"=",
"validation":"",
"inputType":"dropdown"
},
"RhsValue":"true"
},
{
"LhsAttributeDefinition":{
"attribute":{
"key":"isForTablet",
"value":"IsForTablet"
}
},
"Operator":{
"name":"equals",
"description":"=",
"validation":"",
"inputType":"dropdown"
},
"RhsValue":"true"
}
]
]
}
Das .Where(x => (x.isHighBandwidth == true && x.isForMobile == true) || (x.isHighBandwidth == true && x.isForTablet == true))
Hier erzeugen sollte ist, was ich habe dies die Expression Bibliothek erreichen mit:
MethodInfo contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
Expression finalExpression = null;
List<ParameterExpression> paramsArray = new List<ParameterExpression>();
foreach (var conditionList in conditionLists)
{
Expression andGroup = null;
foreach (var condition in conditionList)
{
Expression expression = null;
ParameterExpression param = null;
ConstantExpression constant = null;
switch (condition.LhsAttributeDefinition.Attribute.Key)
{
case "title":
param = Expression.Parameter(typeof(string), "LearningItem.Title");
constant = Expression.Constant(condition.RhsValue, typeof(string));
expression = Expression.Call(param, contains, constant);
break;
case "isHighBandwidth":
param = Expression.Parameter(typeof(string), "IsHighBandwidth");
constant = Expression.Constant(condition.RhsValue, typeof(string));
expression = Expression.Equal(param, constant);
break;
case "isForMobile":
param = Expression.Parameter(typeof(string), "IsForMobile");
constant = Expression.Constant(condition.RhsValue, typeof(string));
expression = Expression.Equal(param, constant);
break;
case "isForTablet":
param = Expression.Parameter(typeof(string), "IsForTablet");
constant = Expression.Constant(condition.RhsValue, typeof(string));
expression = Expression.Equal(param, constant);
break;
}
paramsArray.Add(param);
if (andGroup != null)
{
Expression.And(andGroup, expression);
}
else
{
andGroup = expression;
}
}
//OR the expression tree created above
if (finalExpression != null)
{
Expression.Or(finalExpression, andGroup);
}
else
{
finalExpression = andGroup;
}
}
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { query.ElementType },
query.Expression,
Expression.Lambda<Func<Activity, bool>>(finalExpression, paramsArray.ToArray<ParameterExpression>()));
return query;
Also mein Gedanke ist, dass im Inneren einer verschachtelten for-Schleife, ich baue die AND-Abfragen und die OR-Abfragen als einen großen Ausdruck, und dann erstelle ich die Lambda-Abfrage ganz am Ende. Ich sammle Parameter auf dem Weg in eine paramsArray (Liste).
Mein Problem ist, dass bei der Ausführung, explodiert es sagen, dass 'ParameterExpression of type 'System.String' cannot be used for delegate parameter of type 'INOLMS.Data.Activity''
. Ich nehme an, dies ist, weil der Parameter, den ich bisher gesammelt habe, nur eine Zeichenfolge ist (mein Beispiel Anfrage Körper ist nur eine einzelne Bedingung mit IsHighBandwidth true), und es mag nicht, dass ich einen String-Parameter nehme und versuche um eine Activity
Abfrage zu erhalten.
Was mache ich hier falsch?
Wow, das war super hilfreich. Vielen Dank! –