EF Core 2.1 在 Sum complex 和 Grouping 时在本地求值
EF Core 2.1 evaluates locally when Sum complex and Grouping
我正在使用 EF Core 2.1,查询不会在 SQL 服务器端计算。
此查询中使用的模型是:
public class V_TurnoverByDivision
{
public long Id { get; set; }
public decimal LineAmount { get; set; }
public DateTime? PostingDate { get; set; }
public decimal Quantity { get; set; }
public decimal UnitCostLcy { get; set; }
public string DivisionCode { get; set; }
public string DivisionDescription { get; set; }
public string TopDivisionCode { get; set; }
public string TopDivisionDescription { get; set; }
public decimal RUCAmount { get; set; }
}
这条 LINQ 语句 运行 完全在 SQL 服务器:
return query
.GroupBy(g => new { g.DivisionCode, g.DivisionDescription, g.TopDivisionCode, g.TopDivisionDescription, g.PostingDate })
.Select(s =>
new V_TurnoverByDivision
{
DivisionCode = s.Key.DivisionCode,
DivisionDescription = s.Key.DivisionDescription,
TopDivisionCode = s.Key.TopDivisionCode,
TopDivisionDescription = s.Key.TopDivisionDescription,
PostingDate = s.Key.PostingDate,
LineAmount = s.Sum(ss => ss.LineAmount),
RUCAmount = s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
});
并生成以下 SQL
SELECT
[v].[BIInvCNLinesID]
,[v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[LineAmount]
,[v].[PostingDate]
,[v].[Quantity]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[UnitCostLcy]
FROM [V_TurnoverByDivision] AS [v]
WHERE [v].[PostingDate] >= @__firstDayOfcurrentMonth_0
ORDER BY [v].[DivisionCode], [v].[DivisionDescription], [v].[TopDivisionCode], [v].[TopDivisionDescription], [v].[PostingDate]
此 LINQ 语句有效但在内存中执行 GroupBy
我在输出中收到警告 windows
Microsoft.EntityFrameworkCore.Query:警告:无法翻译 LINQ 表达式 'Sum()',将在本地求值。
但是当我使用这个查询时
return query
.GroupBy(g => new { g.DivisionCode, g.DivisionDescription, g.TopDivisionCode, g.TopDivisionDescription, g.PostingDate })
.Select(s =>
new V_TurnoverByDivision
{
DivisionCode = s.Key.DivisionCode,
DivisionDescription = s.Key.DivisionDescription,
TopDivisionCode = s.Key.TopDivisionCode,
TopDivisionDescription = s.Key.TopDivisionDescription,
PostingDate = s.Key.PostingDate,
LineAmount = s.Sum(ss => ss.LineAmount)
});
};
和 SQL 生成的查询应该是:
SELECT
[v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[PostingDate]
,SUM([v].[LineAmount]) AS [LineAmount]
FROM [V_TurnoverByDivision] AS [v]
WHERE [v].[PostingDate] >= @__firstDayOfcurrentMonth_0
GROUP BY [v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[PostingDate]
如何解决问题:
RUCAmount = s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
这是 EF Core GroupBy
翻译限制(可能会在未来的某个版本中解决)。为了可以翻译成 SQL,聚合方法表达式应该是简单的 属性 访问器。
这就是为什么
s.Sum(ss => ss.LineAmount)
翻译,但是
s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
没有。
因此解决方案是预先 select 聚合所需的表达式。一种方法是对元素 select 或:
使用 GroupBy 重载
return query
.GroupBy(e => new // Key
{
e.DivisionCode,
e.DivisionDescription,
e.TopDivisionCode,
e.TopDivisionDescription,
e.PostingDate
},
e => new // Element
{
e.LineAmount,
RUCAmount = e.LineAmount - (e.Quantity * e.UnitCostLcy) // <--
})
.Select(g => new V_TurnoverByDivision
{
DivisionCode = g.Key.DivisionCode,
DivisionDescription = g.Key.DivisionDescription,
TopDivisionCode = g.Key.TopDivisionCode,
TopDivisionDescription = g.Key.TopDivisionDescription,
PostingDate = g.Key.PostingDate,
LineAmount = g.Sum(e => e.LineAmount),
RUCAmount = g.Sum(e => e.RUCAmount) // <--
});
我正在使用 EF Core 2.1,查询不会在 SQL 服务器端计算。
此查询中使用的模型是:
public class V_TurnoverByDivision
{
public long Id { get; set; }
public decimal LineAmount { get; set; }
public DateTime? PostingDate { get; set; }
public decimal Quantity { get; set; }
public decimal UnitCostLcy { get; set; }
public string DivisionCode { get; set; }
public string DivisionDescription { get; set; }
public string TopDivisionCode { get; set; }
public string TopDivisionDescription { get; set; }
public decimal RUCAmount { get; set; }
}
这条 LINQ 语句 运行 完全在 SQL 服务器:
return query
.GroupBy(g => new { g.DivisionCode, g.DivisionDescription, g.TopDivisionCode, g.TopDivisionDescription, g.PostingDate })
.Select(s =>
new V_TurnoverByDivision
{
DivisionCode = s.Key.DivisionCode,
DivisionDescription = s.Key.DivisionDescription,
TopDivisionCode = s.Key.TopDivisionCode,
TopDivisionDescription = s.Key.TopDivisionDescription,
PostingDate = s.Key.PostingDate,
LineAmount = s.Sum(ss => ss.LineAmount),
RUCAmount = s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
});
并生成以下 SQL
SELECT
[v].[BIInvCNLinesID]
,[v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[LineAmount]
,[v].[PostingDate]
,[v].[Quantity]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[UnitCostLcy]
FROM [V_TurnoverByDivision] AS [v]
WHERE [v].[PostingDate] >= @__firstDayOfcurrentMonth_0
ORDER BY [v].[DivisionCode], [v].[DivisionDescription], [v].[TopDivisionCode], [v].[TopDivisionDescription], [v].[PostingDate]
此 LINQ 语句有效但在内存中执行 GroupBy
我在输出中收到警告 windows
Microsoft.EntityFrameworkCore.Query:警告:无法翻译 LINQ 表达式 'Sum()',将在本地求值。
但是当我使用这个查询时
return query
.GroupBy(g => new { g.DivisionCode, g.DivisionDescription, g.TopDivisionCode, g.TopDivisionDescription, g.PostingDate })
.Select(s =>
new V_TurnoverByDivision
{
DivisionCode = s.Key.DivisionCode,
DivisionDescription = s.Key.DivisionDescription,
TopDivisionCode = s.Key.TopDivisionCode,
TopDivisionDescription = s.Key.TopDivisionDescription,
PostingDate = s.Key.PostingDate,
LineAmount = s.Sum(ss => ss.LineAmount)
});
};
和 SQL 生成的查询应该是:
SELECT
[v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[PostingDate]
,SUM([v].[LineAmount]) AS [LineAmount]
FROM [V_TurnoverByDivision] AS [v]
WHERE [v].[PostingDate] >= @__firstDayOfcurrentMonth_0
GROUP BY [v].[DivisionCode]
,[v].[DivisionDescription]
,[v].[TopDivisionCode]
,[v].[TopDivisionDescription]
,[v].[PostingDate]
如何解决问题:
RUCAmount = s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
这是 EF Core GroupBy
翻译限制(可能会在未来的某个版本中解决)。为了可以翻译成 SQL,聚合方法表达式应该是简单的 属性 访问器。
这就是为什么
s.Sum(ss => ss.LineAmount)
翻译,但是
s.Sum(ss => ss.LineAmount - (ss.Quantity * ss.UnitCostLcy))
没有。
因此解决方案是预先 select 聚合所需的表达式。一种方法是对元素 select 或:
使用 GroupBy 重载return query
.GroupBy(e => new // Key
{
e.DivisionCode,
e.DivisionDescription,
e.TopDivisionCode,
e.TopDivisionDescription,
e.PostingDate
},
e => new // Element
{
e.LineAmount,
RUCAmount = e.LineAmount - (e.Quantity * e.UnitCostLcy) // <--
})
.Select(g => new V_TurnoverByDivision
{
DivisionCode = g.Key.DivisionCode,
DivisionDescription = g.Key.DivisionDescription,
TopDivisionCode = g.Key.TopDivisionCode,
TopDivisionDescription = g.Key.TopDivisionDescription,
PostingDate = g.Key.PostingDate,
LineAmount = g.Sum(e => e.LineAmount),
RUCAmount = g.Sum(e => e.RUCAmount) // <--
});