EF Core中如何将Func<T,decimal>变量传入IQueryable的Sum方法?
错误信息
Expression of type 'System.Func
2[KokazGoodsTransfer.Models.Receipt,System.Decimal]' cannot be used for parameter of type 'System.Linq.Expressions.Expression1[System.Func2[KokazGoodsTransfer.Models.Receipt,System.Decimal]]' of method 'System.Decimal Sum[Receipt](System.Linq.IQueryable1[KokazGoodsTransfer.Models.Receipt], System.Linq.Expressions.Expression1[System.Func2[KokazGoodsTransfer.Models.Receipt,System.Decimal]])' (Parameter 'arg1')
代码对比
可正常运行的代码
var sum = await context.Receipts.GroupBy(c => c.ClientId).Select(c => new { c.Key, Sum = c.Sum(c=>c.Amount) }).ToListAsync();
触发错误的代码
Func<Receipt, Decimal> func = c => c.Amount; var sum = await context.Receipts.GroupBy(c => c.ClientId).Select(c => new { c.Key, Sum = c.Sum(func) }).ToListAsync();
原因及解决方法
问题核心是参数类型不匹配:EF Core(Linq to Entities)中,GroupBy分组后的Sum方法要求接收**Expression<Func<Receipt, decimal>>**类型参数,而非普通的Func委托。因为EF需要将表达式树解析为SQL语句执行,普通Func是编译后的委托,无法被EF转换为SQL逻辑。
直接写c.Sum(c=>c.Amount)时,编译器会自动把lambda表达式转为Expression<Func<...>>类型;但显式声明为Func变量后,编译器不会做这个转换,导致类型不兼容。
修正后的代码:
// 将Func改为Expression<Func<...>>类型 Expression<Func<Receipt, Decimal>> expr = c => c.Amount; var sum = await context.Receipts.GroupBy(c => c.ClientId).Select(c => new { c.Key, Sum = c.Sum(expr) }).ToListAsync();
内容的提问来源于stack exchange,提问作者Tariq Hajeer

