[英]How to optimize this query with EF?
我正在尝试使用 EF 优化此查询。 这是我一开始的疑问。
var result = new List<string>();
_dbContext.signumid_organization.ToListAsync().Result.ForEach(organization =>
{
if (CalculateDifferenceBetweenEntriesAndConsummations(null, organization.Id).Result > threshold)
{
return;
}
if (!string.IsNullOrEmpty(organization.Admin))
{
result.Add(organization.Admin);
}
});
return Task.FromResult(result);
现在我尝试优化它并立即拥有它
return Task.FromResult(_dbContext.signumid_organization
.Where(organization => !string.IsNullOrEmpty(organization.Admin) &&
CalculateDifferenceBetweenEntriesAndConsummations(null, organization.Id).Result <=
threshold).Select(x => x.Admin).ToList());
但问题是我抛出了一个异常,它无法翻译查询。 你对我的例外有什么解决办法吗? 或者也许是另一种查询方法?
这是一个例外:
System.InvalidOperationException: LINQ 表达式 'DbSet() .Where(o => !(string.IsNullOrEmpty(o.Admin)) && ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations( phoneNumber: null, organizationId: (int?)o.Id).Result < = __p_0)' 无法翻译。 附加信息:方法“Signumid.ProductProvisioning.ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations”的翻译失败。 如果此方法可以映射到您的自定义函数,请参阅https://go.microsoft.com/fwlink/?linkid=2132413了解更多信息。 方法“Signumid.ProductProvisioning.ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations”的翻译失败。 如果此方法可以映射到您的自定义函数,请参阅https://go.microsoft.com/fwlink/?linkid=2132413了解更多信息。 以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。 有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038 。
这是 CalculateDifferenceBetweenEntriesAndConsummations 所做的:
if (organizationId != null)
{
return await _dbContext.signumid_credit_operation
.Where(x => x.OrganizationId == organizationId && x.OperationType == OperationType.Purchase)
.SumAsync(x => x.Amount)
- await _dbContext.signumid_credit_operation
.Where(x => x.OrganizationId == organizationId && x.OperationType == OperationType.Consummation)
.SumAsync(x => x.Amount);
}
您在数据库和查询数据库的应用程序中混合工作。
.ToList[Async()]
之前的事情发生在数据库中,之后的事情发生在应用程序中。
以下是一些选项:
CalculateDifferenceBetweenEntriesAndConsummations
,并在linq查询中使用Where
中进行计算 - 如果计算足够简单可以转换为 SQL,这将起作用。 调用函数时具有.Result
的片段表明它是异步的,这使事情变得复杂,但也许它不必是异步的。CalculateDifferenceBetweenEntriesAndConsummations
- 你最初拥有的边点:
return Task.FromResult(_dbContext.signumid_organization
.Where(Select(x => x.Admin).ToList());
应该很可能是
await _dbContext.signumid_organization
.Where(Select(x => x.Admin).ToListAsync();
这同样适用于_dbContext.signumid_organization.ToListAsync().Result.
这应该是`(等待_dbContext.signumid_organization.ToListAsync())。
在CalculateDifferenceBetweenEntriesAndConsummations 发布后更新。
这 3 个查询可以在 SQL 中合并为一个,看起来像这样:
SELECT
name
FROM signumid_organization org
JOIN signumid_credit_operation co on co.OrganizationId = org.Id
WHERE co.OperationType in (number_for_Purchase, number_for_Consummation)
GROUP BY org.Id
HAVING
( SUM(CASE co.OperationType = number_for_Purchase THEN Amount ELSE 0 END)
- SUM(CASE co.OperationType = number_for_Consummation THEN Amount ELSE 0 END)
> threshold -- or '<=', I'm not sure
您可以完成此查询,然后从您的代码中执行此查询,或者完成此查询并将其转换为 LINQ。
好吧,一切都可以在服务器上完成:
var result = await _dbContext.signumid_credit_operation
.Where(x => !string.IsNullOrEmpty(x.Admin))
.GroupBy(x => new { x.OrganizationId, organization.Admin })
.Select(g => new
{
g.Key.OrganizationId,
g.Key.Admin,
Difference = g.Sum(x => x.OperationType == OperationType.Purchase ? x.Amount : 0)
- g.Sum(x => x.OperationType == OperationType.Consummation ? x.Amount : 0)
})
.Where(x => x.Difference <= 100)
.Select(x => x.Admin)
.ToListAsync();
return result;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.