我按照ASP.NET博客中的official guide将ASP.NET Core项目从 2.0.x 升级到 2.1.0-rc1 。 EF Core 包也更新为相同版本。我使用的数据库提供程序是Microsoft.EntityFrameworkCore.SqlServer。我正在等待这次升级,因为我需要很多LINQ GroupBy translation功能。我的一个疑问如下:
await _db.Documents
.ApplyFilter(options)
.Where(x => x.SubscriptionId == subscriptionId && x.Status != DocumentStatus.Deleted)
.GroupBy(document => new { document.SubscriptionId })
.Select(group => new {
Total = group.Sum(x => x.Total),
TotalDiscount = group.Sum(x => x.TotalDiscount),
TotalNet = group.Sum(x => x.TotalNet != null ? x.TotalNet.Value * (decimal)x.CurrencyRate : 0),
SubTotal = group.Sum(x => x.SubTotal != null ? x.SubTotal.Value * (decimal)x.CurrencyRate : 0),
TotalSalesTax = group.Sum(x => x.TotalSalesTax != null ? x.TotalSalesTax.Value * (decimal)x.CurrencyRate : 0),
TotalTax = group.Sum(x => x.TotalTax != null ? x.TotalTax.Value * (decimal)x.CurrencyRate : 0),
TotalPayable = group.Sum(x => x.TotalPayable != null ? x.TotalPayable.Value * (decimal)x.CurrencyRate : 0)
})
.ToListAsync();
当此查询运行时,我仍会收到一条警告:
EFCore Linq查询无法翻译,将在本地进行评估。
所以我想问一下,如果我做某事(非常)错了,或者这个功能还没有公布,那么这个功能还没有?你有没有尝试过类似的东西?提前感谢您的帮助。
对于测试的摇晃,尝试将以下查询(从Sum
方法中移除条件检查)作为 Ivan Stoev 在评论中建议,但结果是相同的。
await _db.Documents
.ApplyFilter(options)
.Where(x => x.SubscriptionId == subscriptionId && x.Status != DocumentStatus.Deleted)
.GroupBy(document => new { document.SubscriptionId })
.Select(group => new {
Total = group.Sum(x => x.Total),
TotalDiscount = group.Sum(x => x.TotalDiscount),
TotalNet = group.Sum(x => x.TotalNet),
SubTotal = group.Sum(x => x.SubTotal),
TotalSalesTax = group.Sum(x => x.TotalSalesTax),
TotalTax = group.Sum(x => x.TotalTax),
TotalPayable = group.Sum(x => x.TotalPayable)
})
.ToListAsync();
经过实验,我发现了以下几点。我发布它以防有人有同样的问题。以下查询完美地转换为T-SQL语句,因此不在客户端上进行评估。
await (from d in _db.Documents.ApplyFilter(options)
where d.SubscriptionId == subscriptionId && d.Status != DocumentStatus.Deleted
group d by d.SubscriptionId into g
select new {
Total = g.Sum(x => x.Total/* * Convert.ToDecimal(x.CurrencyRate)*/),
TotalDiscount = g.Sum(x => x.TotalDiscount/* * Convert.ToDecimal(x.CurrencyRate)*/),
TotalNet = g.Sum(x => x.TotalNet/* * Convert.ToDecimal(x.CurrencyRate)*/),
SubTotal = g.Sum(x => x.SubTotal/* * Convert.ToDecimal(x.CurrencyRate)*/),
TotalSalesTax = g.Sum(x => x.TotalSalesTax/* * Convert.ToDecimal(x.CurrencyRate)*/),
TotalTax = g.Sum(x => x.TotalTax/* * Convert.ToDecimal(x.CurrencyRate)*/),
TotalPayable = g.Sum(x => x.TotalPayable/* * Convert.ToDecimal(x.CurrencyRate)*/)
}).ToListAsync();
明显的区别在于我使用 LINQ查询语法而不是扩展方法。此外,我将CurrencyRate
属性的乘法注释为,这也导致在本地评估查询。这看起来很奇怪,因为查询语法也可以在扩展方法中进行翻译。
我还在Entity Framework Core的Github存储库中打开了一个问题 您可以找到here
答案 0 :(得分:0)
GroupBy是一只红鲱鱼。
使用查询语法编译为使用扩展方法,这不是问题。
我在编辑版本和查询语法版本之间可以看到的唯一区别是,在仍然在本地评估group by的情况下,您会_db.Documents.ApplyFilter(...)
。我猜这会导致返回类型转移到其他东西,并且选择了错误的重载,或者一些混淆查询转换器的类似细节 - 这将导致所有的LINQ运算符( Where,Select,GroupBy等在本地进行评估。
答案 1 :(得分:0)
在我的情况下,此查询在客户端评估了分组:
await context.MyCollection
.GroupBy(x => x.Tag.Id)
.ToDictionaryAsync(x => x.Key, x => x.Count());
将其更改为以下内容可使其在服务器端进行评估:
await context.MyCollection
.GroupBy(x => x.Tag.Id)
.Select(g => new {g.Key, Count = g.Count()})
.ToDictionaryAsync(arg => arg.Key, arg => arg.Count);