2017-06-19 8 views
0

j'ai donc une énorme requête EntityFramework avec EntityFramework, mais de rester simple ici un petit exemple:C# opérateurs dynamiques dans LINQ Expression pour EntityFramework

var amount = 10; 

myArticles.GroupBy(p => p.Id) 
    .Where(grp => grp.Sum(k => k.Amount) > amount 

Selon certains paramètres que j'ai < amount ou == amount.

Bien sûr, je ne veux pas écrire toujours toute requête à nouveau, donc je suis venu avec ceci:

Expression<Func<IGrouping<MyEntity, MyXy>, bool>> whereClause; 

puis en fonction des paramètres d'entrée par exemple:

whereClause = grp => grp.Sum(k => k.Amount) > amount; 
myArticles.GroupBy(p => p.Id) 
    .Where(whereClause); 

maintenant à la question: Est-il possible de rendre l'opérateur dynamique avec Expressions? Ce que je veux écrire quelque chose comme ceci:

Expression<Func<decimal, int, bool>> operatorExpression = (arg1, arg2) => arg1 == arg2; 
whereClause = grp => operatorExpression.Invoke(grp.Sum(k => k.Amount), amount); 

Je suis conscient qu'il ya LinqKit, mais je veux vraiment savoir s'il est possible de résoudre ce juste en utilisant des arbres d'expression et de la façon dont il est complexe. Je ne veux pas faire un Func hors de l'opérateurexpression car le résultat devrait être calculé sur le SQL Server, pas en mémoire.

+0

Si, en utilisant simplement Expression Trees *, vous voulez dire des expressions de temps de compilation en C# pur sans helpers de traitement d'expression personnalisés (comme LINQKit ou similaire), non, ce n'est pas possible. Recherchez SO pour * "composer expression" * et vous trouverez de nombreux exemples applicables à votre cas simple. –

+0

Vous demandez essentiellement à quel point il serait difficile de réimplémenter LINQKit. Pourquoi ne regardez-vous pas son code source et décidez vous-même? – svick

Répondre

0

Malheureusement, vous ne pouvez pas .Invoke une expression lambda.

Syntaxiquement vous pouvez écrire

grp => operatorExpression.Compile()(grp.Sum(k => k.Amount), amount) 

qui vous donne une expression qui contient toutes les informations, mais ne sera pas compris par le cadre de l'entité.

Mais avec une certaine manipulation d'expression, cela peut être converti en

grp => <body-of-lambda-with-parameters-replaced-by-corresponding-arguments> 

Dans votre exemple, le corps du lambda est arg1 == arg2, vous remplacez toute ocurrence de arg1 avec grp.Sum(k => k.Amount) et arg2 avec amount.

Voir my other answer avec du code pour cela.