Reputation: 963
I want to send a sum after I have collected multiple fields in the database. But I need to write the fields as string. I may not be able to fully explain my problem, I will try to exemplify it.
What I want to do is this code's lambda state
I want to do :
expression = x => x.M1_TotalLoss + x.M2_TotalLoss;
My Code :
var param = Expression.Parameter(typeof(FooDomain), "x");
var value = Expression.Property(param, ("M1_TotalLoss"+"M2_TotalLoss"));
var rest = Expression.Lambda<Func<FooDomain, double>>(value, param);
var result = myContext.FooDomain().
GroupBy(gp=>gp.Year).
Select(s => new
{
TotalLoss = Math.Round(s.AsQueryable().Sum(rest), 2)
}).
OrderByDescending(o => o.TotalLoss).
ToList();
But since I can not write the predicate correctly, I get the following error:
exceptionMessage= Example feature 'M1_TotalLossM2_TotalLoss' not defined for type 'FooDomain'.
Upvotes: 1
Views: 207
Reputation: 205629
Let see what we have here:
x => x.M1_TotalLoss + x.M2_TotalLoss
x
apparently is a parameter, so
var param = Expression.Parameter(typeof(FooDomain), "x");
is ok.
x.M1_TotalLoss
and x.M2_TotalLoss
are properties of the parameter x
called respectively "M1_TotalLoss"
and "M2_TotalLoss"
, so let reflect that:
var value1 = Expression.Property(param, "M1_TotalLoss");
var value2 = Expression.Property(param, "M2_TotalLoss");
and x.M1_TotalLoss + x.M2_TotalLoss
is just the add operation of the two:
var value = Expression.Add(value1, value2);
and you are done - the rest of the code is ok.
What about more than 2 properties?
Since op1 + op2 + op3
is equivalent of (op1 + op2) + op3
, or with method notation Add(Add(op1, op2), op3)
, it can be seen that N additions can be described recursively as adding the next operand to the result of the addition of the previous operands. Which can easily be implemented with LINQ Aggregate
method.
So given IEnumerable<string>
containing the desired property names, you can use something like this:
var propertyNames = new [] { "M1_TotalLoss", "M2_TotalLoss", };
var param = Expression.Parameter(typeof(FooDomain), "x");
var value = propertyNames.Select(name => Expression.Property(param, name))
.Aggregate<Expression>(Expression.Add);
// the rest of the code (same as yours)
Upvotes: 2