实体框架4.1查询需要很长的时间(5秒)才能完成

实体框架4.1查询需要很长的时间(5秒)才能完成

问题描述:

我有DbContext(称为“MyContext”),其中包含大约100个DbSets。实体框架4.1查询需要很长的时间(5秒)才能完成

在域类中,我有一个包含10个直接子类的Document类(如PurchaseOrder,RequestForQuotation等)。 heirarchy被映射为TPT策略。 也就是说,在我的数据库中,有一个Document表和其他表,如子类的PurchaseOrder和RequestForQuotation。

当我做一个查询,如:

Document document = myContext.Documents.First(); 

查询花了5秒,无论是我第一次运行它或随后。

的查询,如:

Document document = myContext.Documents.Where(o => o.ID == 2); 

还需要长达。

这是EF4.1的问题(如果是这样,EF4.2的帮助)还是这是查询代码的问题?

我不能肯定,通过代码优先实际使用的ObjectQuery但是你可以尝试调用.ToTraceString()方法对他们看到的是生成了什么SQL,像这样露出DbSet:

var query = myContext.Documents.Where(o => o.ID == 2); 
Debug.WriteLine(query.ToTraceString()); 

一旦你得到SQL,你可以确定它是查询还是EF引起延迟。根据基类的复杂性,查询可能会包含许多额外的列,这可以通过投影来避免。使用预测,可以这样进行查询:

var query = from d in myContext.Documents 
      where d.ID == 2 
      select new 
      { 
       o.Id 
      }; 

这应该基本上执行SELECT ID FROM Documents WHERE ID = 2查询,你可以测量这个需要多久才能获得进一步的信息。当然,预计的查询可能不适合您的需求,但它可能会让您走上正轨。如果这仍然需要5秒钟,您应该查看数据库本身而不是EF的性能问题。

更新 显然与代码首先,你可以使用的ToString(),而.ToTraceString(),感谢Slauma用于察觉。

+2

'query.ToString()',而不是'ToTraceString()'显示了SQL使用'DbContext'时。 – Slauma

+0

@Slauma谢谢,这会派上用场。 –

您是否尝试使用SQL配置文件查看实际发送到数据库的内容?这可能是因为您的文档中有太多连接未设置为延迟加载,因此查询必须一次完成所有连接,这会导致列数过多。尝试发送一个简单的查询只有一个返回列。

正如您可以阅读here,在EF中有关于TPT的一些性能问题。

的EF团队公开宣布了一些修复的June 2011 CTP,包括TPT查询优化,但不包括在EF 4.2,你可以在评论中读取this answer

在最糟糕的情况下,这些修补程序将仅在.NET 4.5中发布。我希望它会更快......

+1

我认为TPT继承很可能是问题的根源。 10个表的SQL查询将会很糟糕。 –

+0

TPT继承可能非常有用,但我也有关于其性能的问题。我正在使用5-6张桌子。有10张桌子,我想它会变得更糟。这是我等待这些优化被纳入EF的原因之一。 –

+0

假设TPT是原因,您使用其他解决方案来解决它吗? – swirlobt

我刚刚在ExecuteFunction中存在5秒的延迟,这个存储过程在从SQL Management Studio调用时即时运行。我通过重写程序来修复它。

看来EF(和SSRS BTW)会尝试在存储过程和某些(通常是复杂的)过程中执行类似“准备”的操作,这可能需要很长时间。

一个快速和肮脏的解决办法是复制,然后用内部变量替换您的SP参数:

create proc ListOrders(@CountryID int = 3, @MaxOrderCount int = 20) 
as 
declare @CountryID1 int, @MaxOrderCount1 int 
set @CountryID1 = @CountryID 
set @MaxOrderCount1 = @MaxOrderCount 

select top (@MaxOrderCount1) * 
from Orders 
where CountryID = @CountryID1