2017-04-20 90 views
0

我在我的ASP.NET MVC应用程序中使用实体框架,并且在通过LINQ从SQL Server加载数据时遇到了一个问题。我的查询在4秒内返回结果,但我需要花更少的时间,仍然寻找更好的解决方案。如何减少Entity Framework Linq查询执行时间?

这里是我的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(); 
+5

您是否尝试过加载较少的实体? – Marco

+0

检查您是否在Id和OrganizationId上创建了索引。索引可以加速这种情况。 – Tony

+3

您确定需要_ALL_这些其他表和数据,因为这将产生相当多的JOIN操作,这可能会很昂贵。此外,你可以用'FirstOrDefault()'替换你的'Where()'子句来清理一些东西,你可能不需要为每个Include()调用AsNoTracking()函数。 –

回答

0

无需获得多个实体履行谓语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()

+0

感谢您的代码,运气很好,得到了和我以前的结果一样的结果。 – Surendar

+0

'context.CreateObjectSet ().AsNoTracking()'...似乎很奇怪,你不想要像'context.Users..AsNoTracking()'...这样的东西吗?你的用户应该已经被创建,现在你正在查询/过滤现有的数据(而不是创建新的数据库)。或者,这可能只是一个命名不清的方法? – Fredrik

+0

似乎它必须启动表结构,所以不能 – Surendar

0

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

在这一点上,获得或丢失的速度取决于程序的sql的结构,并关注数据库中使用的索引以提高速度。

Linq SQL实际上是样板文件,不是为速度而设计的。

我已经完成了多个EF项目。


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

另外,您可以考虑使用SQL CTE(公共表Experssions)一次构建您的查询,直到数据正好满足需要。

+0

感谢您的指示,以前曾尝试在存储过程和视图,但由于过多的联接无法获得预期的结果。这就是为什么寻找修复在EF中。 – Surendar

+0

@Surendar我会在Linqpad中构建我的linq查询,然后切换到查看生成的SQL。这会给我一个关于如何在存储过程中构建SQL的想法。你也可以考虑使用SQL CTE来一次构建你的查询,直到数据正好满足需要。 HTH – OmegaMan

+0

OmegaMan,这是有道理的,将在Linqpad尝试这个,谢谢。 – Surendar