【问题标题】:How to optimize this query with EF?如何使用 EF 优化此查询?
【发布时间】:2022-07-21 18:51:38
【问题描述】:

我正在尝试使用 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());

但问题是我抛出了一个异常,它无法翻译查询。你对我的例外有什么解决办法吗?或者也许是另一种查询方法?

这是个例外:ystem.InvalidOperationException: The LINQ expression 'DbSet&lt;Organization&gt;() .Where(o =&gt; !(string.IsNullOrEmpty(o.Admin)) &amp;&amp; ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations( phoneNumber: null, organizationId: (int?)o.Id).Result &lt;= __p_0)' could not be translated. Additional information: Translation of method 'Signumid.ProductProvisioning.ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations' failed. If this method can be mapped to your custom function, see https://go.microsoft.com/fwlink/?linkid=2132413 for more information. Translation of method 'Signumid.ProductProvisioning.ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations' failed. If this method can be mapped to your custom function, see https://go.microsoft.com/fwlink/?linkid=2132413 for more information. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

这是 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);
        }

【问题讨论】:

  • 只能使用 SQL 查询数据库。 EF 将 LINQ 查询转换为 SQL,不能做任何在 SQL 中不可能的事情。无法翻译本地方法调用CalculateDifferenceBetweenEntriesAndConsummations(null, organization.Id).Result
  • 您是否尝试过搜索错误。很有可能ProductProvisioningRepository.CalculateDifferenceBetweenEntriesAndConsummations 是问题所在,因为在 SQL 中无法做到这一点。
  • @Ralf 即使有一个这样调用的函数,这也不是使用它的方法。
  • CalculateDifferenceBetweenEntriesAndConsummations 是做什么的?
  • @PanagiotisKanavos 我更新了问题

标签: c# asp.net .net entity-framework entity-framework-core


【解决方案1】:

您在数据库和查询数据库的应用程序中混合工作。

.ToList[Async()] 之前的事情发生在数据库中,之后的事情发生在应用程序中。

这里有一些选项:

  • 在数据库中创建数据库函数CalculateDifferenceBetweenEntriesAndConsummations,并在linq查询中使用
  • 不要使用函数并在Where 中进行计算 - 如果计算足够简单,可以转换为 SQL,这将起作用。调用函数时带有 .Result 的 sn-p 表明它是异步的,这会使事情变得复杂,但也许它不必是异步的。
  • 从数据库中获取所有记录,然后应用 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.,它应该是 `(await _dbContext.signumid_organization.ToListAsync())。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2016-07-22
    • 2017-03-01
    • 2023-04-02
    相关资源
    最近更新 更多