【问题标题】:How to reduce Entity Framework Linq query execution time? [duplicate]如何减少 Entity Framework Linq 查询执行时间? [复制]
【发布时间】:2017-04-21 23:05:58
【问题描述】:

我在我的 ASP.NET MVC 应用程序中使用实体框架,并且在通过 LINQ 从 SQL Server 加载数据时遇到问题。我的查询在 4 秒内返回结果,但我需要更短的时间,仍在寻找更好的解决方案。

这是我的 linq 查询:

var user =
    context.CreateObjectSet<DAL.ProductMaster>()
        .AsNoTracking()
        .Include("Product1").AsNoTracking()
        .Include("Product2").AsNoTracking()
        .Include("Product3").AsNoTracking()
        .Include("Product4").AsNoTracking()
        .Include("Product5").AsNoTracking()

        .Where(x => x.Id == request.Id)
         ).FirstOrDefault();

【问题讨论】:

  • 你试过加载更少的实体吗?
  • 您确定需要 ALL 的那些其他表和数据,因为这会产生相当多的 JOIN 操作,这可能会很昂贵。此外,您可以用FirstOrDefault() 替换您的Where() 子句以稍微清理一下,您可能不需要为每个单独的Include() 调用AsNoTracking()
  • 尝试编写您希望手动对数据库执行的 sql。如果运行良好,请尝试优化您的 linq
  • 考虑使用.Select() 运算符来准确地获取您想要的内容,而不是看起来像数据库很大一部分的大杂烩。
  • 在多个查询中获取数据 + 删除 organizationsList.Count()!= 0(并且,与性能无关:删除除一个 AsNoTracking 调用之外的所有调用)。

标签: c# entity-framework linq


【解决方案1】:

不需要让多个实体满足Where()中的谓词,然后选择第一个;只需直接致电FirstOrDefault()

if (request == null || organizationsList == null || !organizationsList.Any())
    return; 

var user = context.CreateObjectSet<DAL.User>()
                  .AsNoTracking()
                  .Include("UsersinPrograms.FollowUps")
                  .Include() ...
                  .FirstOrDefault(x => x.Id == request.userId && organizationsList.Contains(x.OrganizationId)));

另外,删除您不需要的Include()

【讨论】:

  • 感谢您的代码,运气不好,我得到的结果与我之前的结果相同。
  • context.CreateObjectSet&lt;DAL.User&gt;().AsNoTracking() ... 看起来很奇怪,你不想要context.Users..AsNoTracking() ...之类的东西吗?您应该已经创建了用户,现在您正在查询/过滤现有数据(未创建新的数据库集)。或者这只是一个名字不好的方法?
  • 好像必须要启动表结构,所以不能
【解决方案2】:

对于这个和任何大规模的业务逻辑操作,应该创建存储过程,而不是基于 Linq。然后在 EF 中创建一个 DTO 对象来处理结果并使用 EF 中的过程。

此时,速度的提高或降低取决于过程的 sql 的结构方式,并着眼于数据库中使用的索引,以提高速度。

Linq SQL 是真正的样板文件,并不是为提高速度而设计的。

我已经在多个 EF 项目中做到了这一点。


还可以在 Linqpad 中构建他们的 linq 查询,然后切换到查看生成的 SQL。这将提供一个关于如何在存储过程中构建 SQL 的想法。

您还可以考虑使用 SQL CTE(通用表表达式)一次一步地构建您的查询,直到数据刚好满足需要。

【讨论】:

  • 感谢您的指导,之前在存储过程和视图中尝试过,但由于连接数量过多无法获得预期结果。这就是为什么要在 EF 中修复。
  • @Surendar 我会在 Linqpad 中构建我的 linq 查询,然后切换到查看生成的 SQL。这会给我一个关于如何在存储过程中构造我的 SQL 的想法。您也可以考虑使用 SQL CTE 一次一步地构建您的查询,直到数据刚好满足需要。 HTH
  • OmegaMan,这很有道理,将在 Linqpad 中尝试一下,谢谢。
  • @Surendar 如果您对从 EntityFramework 生成的 IQueryable&lt;T&gt; 对象执行 .ToString(),如果您想查看您的查询,它还会为您提供将发送到服务器的查询正在生成 LINQ 语句。您需要将示例查询中的 .FirstOrDefault() 替换为 .ToString() 才能正常工作。
  • -1 因为生成的查询和存储过程都进入查询优化器并获得查询执行计划。该计划确定是否使用表的索引以及访问和组合表的顺序。优化器的选择是主要的性能考虑因素。 “如何使用索引构建过程”是完全不正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
相关资源
最近更新 更多