linq 如何使用ef核心将Func〈T,decimal>类型变量从IQueryable发送到sum

hwamh0ep  于 2022-12-06  发布在  其他
关注(0)|答案(2)|浏览(154)

我需要在函数参数中发送一个lambda,但当我这样做时,我有错误消息
类型为“系统.函数2[KokazGoodsTransfer.Models.Receipt,System.Decimal]' cannot be used for parameter of type 'System.Linq.Expressions.Expression 1[系统.函数2[KokazGoodsTransfer.Models.Receipt,System.Decimal]]' of method 'System.Decimal Sum[Receipt](System.Linq.IQueryable 1[KokazGoodsTransfer.Models.Receipt],系统.链接.表达式.表达式1[System.Func 2[KokazGoodsTransfer.Models.Receipt,系统.Decimal]])"的表达式(参数”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();

谢谢你

d7v8vwbk

d7v8vwbk1#

EF通常需要一个expression tree来将代码转换为实际的SQL查询。
你可以试试这样的方法(虽然没有经过测试,但据我所知,在某些情况下这样的技巧是有效的):

Expression<Func<Receipt, Decimal>> func = c => c.Amount;
var sum = await context.Receipts
    .GroupBy(c => c.ClientId)
    .Select(c => new { c.Key, Sum = c.AsQueryable().Sum(func) })
    .ToListAsync();

否则,你可能需要手动构建select语句表达式(这并不容易),或者查看第三方库,如LINQKit,它允许使用Func的一些魔术。

Expression<Func<Receipt, Decimal>> func = c => c.Amount;
var sum = await context.Receipts
    .AsExpandable() // or WithExpressionExpanding on the context DI set up
    .GroupBy(c => c.ClientId)
    .Select(c => new { c.Key, Sum = c.Sum(func.Compile()) })
    .ToListAsync();
ruyhziif

ruyhziif2#

你必须使用Expression<Func<Receipt, Decimal>>而不是Func。但是如果没有第三方扩展,它也是不可翻译的。我建议使用LINQKit。它只需要配置DbContextOptions

builder
    .UseSqlServer(connectionString) // or any other provider
    .WithExpressionExpanding();     // enabling LINQKit extension

然后,您的查询将以下列方式运作:

Expression<Func<Receipt, Decimal>> func = c => c.Amount;

var sum = await context.Receipts.GroupBy(c => c.ClientId)
  .Select(c => new { c.Key, Sum = c.Sum(x => func.Invoke(x)) })
  .ToListAsync();

相关问题