gpt4 book ai didi

c# - EF Core 2.1 在分组后进行子查询和聚合时在本地进行评估

转载 作者:行者123 更新时间:2023-11-30 13:43:43 24 4
gpt4 key购买 nike

因此 EF Core 2.1 在 SQL 服务器上计算 GroupBy LINQ 表达式(当使用 SQL 提供程序时)。

这很棒但是当查询变得有点复杂时我遇到了问题。

用于这些查询的模型是:

public class Invoice
{
public string Status {get; set;}
public string InvoiceType {get; set;}
public decimal InvoicePayments {get; set;}
public decimal EligibleValue {get; set;}
}

此 LINQ 语句完全在 SQL Server 中运行:

data
.GroupBy(i => new { i.Status, i.InvoiceType })
.Select(i => new
{
i.Key,
Count = i.Count(),
Total = i.Sum(x => x.EligibleValue)
});

并生成如下SQL

SELECT 
[i].[Status],
[i].[InvoiceType],
COUNT(*) AS [Count],
SUM([i].[EligibleValue]) AS [Col1]
FROM [Invoice] AS [i]
GROUP BY [i].[Status], [i].[InvoiceType]

此 LINQ 语句有效但执行 GroupBy 在内存中:

data
.GroupBy(i => new { i.Status, i.InvoiceType })
.Select(i => new
{
i.Key,
Count = i.Count(),
TotalLessThan100 = i.Where(x => x.InvoicePayments < 100).Sum(y => y.EligibleValue),
TotalLessThan500 = i.Where(x => x.InvoicePayments < 500).Sum(z => z.EligibleValue)
});

我在“输出”窗口中收到一些警告:

    The LINQ expression 'GroupBy(new <>f__AnonymousType0`2(Status = [i].Status, InvoiceType = [i].InvoiceType), [i])' could not be translated and will be evaluated locally.

The LINQ expression 'Count()' could not be translated and will be evaluated locally.

The LINQ expression 'where ([x].InvoicePayments < 100)' could not be translated and will be evaluated locally.

The LINQ expression 'where ([x].InvoicePayments < 500)' could not be translated and will be evaluated locally.

The LINQ expression 'Sum()' could not be translated and will be evaluated locally.

并且生成的 SQL 没有 GroupBy,只有初始查询。

有什么方法可以定义此查询以在 SQL Server 上完全执行?

最佳答案

要遵循的第一条规则是避免 Where 和谓词版本的 CountGroupBy 结果上使用条件 Sum 尽可能。 EF6 能够翻译此类构造,但 SQL 的效率非常低。

所以通常你需要像这样重写查询:

data
.GroupBy(i => new { i.Status, i.InvoiceType })
.Select(g => new
{
g.Key,
Count = g.Count(),
TotalLessThan100 = g.Sum(i => i.InvoicePayments < 100 ? i.EligibleValue : 0),
TotalLessThan500 = g.Sum(i => i.InvoicePayments < 500 ? i.EligibleValue : 0)
});

但是 EF Core 2.1 GroupBy 翻译改进不包括 Sum 除了一个简单的属性选择器,所以上面仍然使用客户端评估。它很可能会在未来的某个版本中得到修复,但在那之前,可以使用以下技巧 - 在包含稍后需要的所有字段的 GroupBy 之前添加中间投影(Select),包括计算的,然后在 GroupBy 之后的聚合中使用它们:

data
.Select(i => new
{
i.Status,
i.InvoiceType,
LessThan100 = i.InvoicePayments < 100 ? i.EligibleValue : 0,
LessThan500 = i.InvoicePayments < 500 ? i.EligibleValue : 0,
})
.GroupBy(i => new { i.Status, i.InvoiceType })
.Select(g => new
{
g.Key,
Count = g.Count(),
TotalLessThan100 = g.Sum(i => i.LessThan100),
TotalLessThan500 = g.Sum(i => i.LessThan500)
});

翻译成:

SELECT [i].[Status], [i].[InvoiceType], COUNT(*) AS [Count], SUM(CASE
WHEN [i].[InvoicePayments] < 100.0
THEN [i].[EligibleValue] ELSE 0.0
END) AS [TotalLessThan100], SUM(CASE
WHEN [i].[InvoicePayments] < 500.0
THEN [i].[EligibleValue] ELSE 0.0
END) AS [TotalLessThan500]
FROM [Invoice] AS [i]
GROUP BY [i].[Status], [i].[InvoiceType]

关于c# - EF Core 2.1 在分组后进行子查询和聚合时在本地进行评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51322006/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com