0

So I have a huge EntityFramework query with EntityFramework, but to keep it simple here a small example:

var amount = 10;

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

Depending on some parameters I have < amount or == amount.

Of course I do not want to always write the whole query again, so I came up with this:

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

and then depending on the input parameters for example:

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

Now to the question: Is it somehow possible to get make the operator dynamic with Expressions? What I want to write is something like this:

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

I am aware that there is LinqKit, but I really want to know if it is possible to solve this just using Expression Trees and how complicated it is. I do not want to make a Func out of the operatorExpression as the result should be computed on the SQL Server, not in memory.

Tim
  • 2,051
  • 17
  • 36
  • If by *just using Expression Trees* you mean pure C# compile time expressions without custom expression processing helpers (like LINQKit or similar), no, it's not possible. Search SO for *"compose expression"* and you'll find many examples which are applicable for your simple case. – Ivan Stoev Jun 19 '17 at 10:46
  • You're basically asking how difficult would it be to reimplement LINQKit. Why don't you have a look at its source code and decide yourself? – svick Jun 19 '17 at 11:51

1 Answers1

0

Unfortunately you cannot .Invoke a lambda expression.

Syntactically you can write

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

which gives you an expression that contains all the information, but won't be understood by entity framework.

But with some expression manipulation this can be converted to

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

In your example, the body of the lambda is arg1 == arg2, so you replace any ocurrence of arg1 with grp.Sum(k => k.Amount), and arg2 with amount.

See my other answer including some code to do this.

tinudu
  • 1,139
  • 1
  • 10
  • 20