按动态聚合分组
Group by Dynamic Aggregate
在下面的代码中,我想将 x.BaseSalary
替换为名称存储在 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 表达式,该表达式 return 是传递的实例参数的成员
(我假设Employees
中的元素是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
通话:
new { Key = group.Key, Avg = group.Average(lambda) }
注意:这仅适用于 int?
类型的成员。我缺乏关于如何更独立于类型的经验,但是您可以计算哪些类型的平均值?但如果有 int
或 double
成员,则可能需要另一个强制转换表达式。
编辑:(将 return 类型更改为 int?
)。根据 关于我的后续问题,你可以试试这个:
new { Key = group.Key, Avg = group.AsQueryable().Average(expression) }
EF6 应该识别对 AsQueryable()
的调用,然后使用正确的 Average
方法(注意我使用 expression
作为参数而不是 lambda
)。 EF Core 和 linq2Sql 不会 使用它。
在下面的代码中,我想将 x.BaseSalary
替换为名称存储在 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 表达式,该表达式 return 是传递的实例参数的成员
(我假设Employees
中的元素是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
通话:
new { Key = group.Key, Avg = group.Average(lambda) }
注意:这仅适用于 int?
类型的成员。我缺乏关于如何更独立于类型的经验,但是您可以计算哪些类型的平均值?但如果有 int
或 double
成员,则可能需要另一个强制转换表达式。
编辑:(将 return 类型更改为 int?
)。根据
new { Key = group.Key, Avg = group.AsQueryable().Average(expression) }
EF6 应该识别对 AsQueryable()
的调用,然后使用正确的 Average
方法(注意我使用 expression
作为参数而不是 lambda
)。 EF Core 和 linq2Sql 不会 使用它。