【问题标题】:How to handle divide by zero in Sum() with efcore如何使用 efcore 在 Sum() 中处理除以零
【发布时间】:2021-04-13 01:16:11
【问题描述】:

我正在努力解决一个错误,该错误影响了我们用于客户洞察的系统。代码如下:

Insights MyInsights = new Insights();
MyInsights.UnpostedInvoiceValue = DatabaseContext.Invoice
.Where(z => z.OwnedBy.TenantId == CurrentTenant.TenantId && z.Posted == false)
.Sum(x => x.Items.Sum(y =>(y.PricePerUnit  /  y.ExchangeRate) * y.Quantity / y.Units.PriceFactor));

问题在于“.ExchangeRate”或“y.Units.PriceFactor”为 0(零)时,因为我们不可能全部除以零,所以我们得到了一个例外。

由于该系统是多租户的,这似乎会影响所有租户,即使只有一个租户的数据中有 0(零)。我原以为情况并非如此,因为我们有一个 Where 子句可以检查租户 ID。

生成的SQL如下:

SELECT (
 SELECT SUM((([y].[PricePerUnit] / [y].[ExchangeRate]) * [y].[Quantity]) / [y.Units].[PriceFactor])
 FROM [InvoiceItem] AS [y]
 LEFT JOIN [Units] AS [y.Units] ON [y].[UnitsId] = [y.Units].[UnitsId]
WHERE [z].[InvoiceId] = [y].[InvoiceId]
)
 FROM [Invoice] AS [z]
 WHERE ([z].[OwnedByTenantId] = @__CurrentTenant_TenantId_0) AND ([z].[Posted] = 0)

返回的异常是:

System.Data.SqlClient.SqlException: 'Divide by zero error encountered.' 

我认为这个问题有两个方面:

  1. 我不明白为什么当只有一个租户的数据中有 0(零)时,这会影响所有租户。
  2. 理想情况下,如果其中一个字段中存在 0(零),Sum() 应该返回 0,但我无法弄清楚,我在 Sum() 函数中尝试的所有内容都无法编译。

谢谢

【问题讨论】:

  • 先贴出异常。其次,EF Core 并不神奇。它生成一个返回所有结果的 SQL 查询。如果出现一个错误,则查询失败。 实际 SQL 查询是什么?
  • 您是否关闭了客户端评估?过于复杂的查询(总和中的总和?)可能会强制 EF Core 加载部分结果并尝试计算客户端上的一些聚合。此外,存储无效的 ExchangeRate 有什么意义?如果没有汇率,则该值应为 1(本地货币)或 NULL(缺少汇率)。如果您想在数据库中存储幻数,您需要在查询中明确处理它们
  • @PanagiotisKanavos 我已提供所要求的信息。汇率无效的原因是数据已被第三方系统导入,我们无法控制。我知道我需要在我们的查询中处理这个问题,我只是想找出处理这个问题的最佳方法。
  • 这不是完整的查询(外部 SELECT 缺少一些字段和外部 SUM)但显示出了什么问题。为了计算嵌套的 SUM,EF Core 生成了一个聚合发票项目的查询和一个计算最终 SUM 的外部查询。
  • 你想做什么?为什么是嵌套总和?如果您想对特定租户的 InvoiceItems 求和,您应该从 InvoiceItem 开始,而不是 Invoice。例如db.InvoiceItems.Where(i=>i.Invoice.OwnedBy.TenantID=.....)

标签: c# entity-framework-core ef-core-2.2


【解决方案1】:

正如 cmets 中提到的,EF 不太适合复杂的查询。但是这个是可行的。

var query = 
  from z in DatabaseContext.Invoice
  from y in z.Items
  where z.OwnedBy.TenantId == CurrentTenant.TenantId && z.Posted == false
  select new 
  {
     Value = y.ExchangeRate == 0 || y.Units.PriceFactor == 0 
       ? 0 
       : (y.PricePerUnit / y.ExchangeRate) * y.Quantity / y.Units.PriceFactor
  }

MyInsights.UnpostedInvoiceValue = query.Sum(x => x.Value);

【讨论】:

    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多