J'ai une liste de listes de conditions envoyées depuis le client. J'ai besoin de prendre cette liste et de créer une clause dynamic where à exécuter par EntityFramework.Arbre d'expression pour créer une erreur de lancement de clause Where dynamique liée aux paramètres
Chaque condition a un opérateur, un attribut et une valeur de droite.
Chaque liste de conditions doit être associée ensemble.
Chaque liste de listes de conditions doit être associée entre elles.
Donc, si nous avions
{
"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"
}
]
]
}
Cela devrait générer .Where(x => (x.isHighBandwidth == true && x.isForMobile == true) || (x.isHighBandwidth == true && x.isForTablet == true))
Voici ce que je dois accomplir cela en utilisant la bibliothèque d'expression:
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;
Donc, ma pensée est que l'intérieur d'une boucle imbriquée, je construis les requêtes AND et les requêtes OU comme une grande expression, puis je crée la requête lambda à la toute fin. Je collecte les paramètres le long du chemin dans un paramsArray (liste).
Mon problème est que lors de l'exécution, il explose en disant que 'ParameterExpression of type 'System.String' cannot be used for delegate parameter of type 'INOLMS.Data.Activity''
. Je suppose que c'est parce que le paramètre que j'ai collecté jusqu'ici est juste une chaîne (mon exemple de corps de requête est juste une seule condition avec IsHighBandwidth true), et il n'aime pas que je prenne un paramètre string et essaye pour obtenir une requête Activity
.
Qu'est-ce que je fais mal ici?
Wow, c'était super utile. Merci beaucoup! –