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

时间:2011-11-17 11:27:11

标签: entity-framework entity-framework-4 entity-framework-4.1

我有DbContext(称为“MyContext”),里面有大约100个DbSets。

在域类中,我有一个包含10个直接子类的Document类(如PurchaseOrder,RequestForQuotation等)。 层次结构用TPT策略映射。 也就是说,在我的数据库中,有一个Document表,其他表如PurchaseOrder,RequestForQuotation用于子类。

当我进行如下查询时:

Document document = myContext.Documents.First();

查询耗时5秒,无论是我第一次运行还是随后运行。

如下的查询:

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

也花了很长时间。

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

4 个答案:

答案 0 :(得分:3)

我不确定代码优先暴露的DbSet实际上是否使用了ObjectQuery,但您可以尝试在它们上调用.ToTraceString()方法来查看生成的SQL,如下所示:

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注意到。

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

EF小组在June 2011 CTP中发布了多项修正,包括TPT查询优化,但它们未包含在EF 4.2中,因为您可以在this answer的评论中阅读。

在最坏的情况下,这些修补程序只会在.NET 4.5中发布。我希望它能早点......

答案 3 :(得分:1)

我刚刚在一个存储过程中在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