按动态汇总分组 [英] Group by Dynamic Aggregate
问题描述
在下面的代码中,我想用其名称存储在feildtoretrive
中的任何其他属性替换x.BaseSalary
:
In the code below I want to replace x.BaseSalary
with any other property whose name is stored in feildtoretrive
:
var feildtoretrive = "BaseSalary"
var groupcal = db.Employees.GroupBy(x=>x.Region)
.Select(group => new {
Key = group.Key,
Avg = group.Average(x => x.BaseSalary)
})
.ToList();
推荐答案
您需要
- 创建一个访问实例成员的
MemberExpression
- 编译一个lambda表达式,该表达式为传递的实例参数返回该成员
(我假设Employees
中的元素属于Employee
类型)
(I assume that the elements in Employees
are of type Employee
)
// the parameter expression for the lambda (your 'x')
var parameter = Expression.Parameter(typeof(Employee));
// the property access expression (your 'x.BaseSalary' or 'x.<feildtoretrive')
var propAccess = Expression.PropertyOrField(parameter, feildtoretrive);
// the build-together and compiled lambda
var expression = (Expression<Func<Employee, int?>>)Expression.Lambda(propAccess, parameter);
您现在可以将lambda
用于x.Average
呼叫:
You can now use lambda
for the x.Average
call:
new { Key = group.Key, Avg = group.Average(lambda) }
一个警告:现在仅适用于int?
类型的成员.我缺乏一些如何独立于类型的经验,但是您可以计算出哪些类型的平均值呢?但是,如果有int
或double
成员,则可能需要另一个强制转换表达式.
A caveat: This only works now for members of type int?
. I'm lacking a little experience on how to do this more type independent, but what types can you calculate an average over? But if there are int
or double
members, another cast expression maybe necessary.
(将返回类型更改为int?
).根据 Ivan Stoev的评论我的后续问题,您可以尝试以下方法:
(changed the return type to int?
). According to Ivan Stoev's comment on my follow up question you could try this:
new { Key = group.Key, Avg = group.AsQueryable().Average(expression) }
EF6 应该识别对AsQueryable()
的调用,然后使用正确的Average
方法(请注意,我将expression
用作参数,而不是lambda
). EF Core和linq2Sql 不会一起使用.
EF6 should recognize the call to AsQueryable()
and then use the correct Average
method (note that I use the expression
as argument instead of the lambda
). EF Core and linq2Sql won't work with that.
这篇关于按动态汇总分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!