entity-framework - EntityFramework : Calling ToList() on IQueryable with ~11. 000 条记录需要 10 秒

标签 entity-framework linq sql-server-2008-r2 entity-framework-4

我想通过 EntityFramework 4 通过 WCF 服务从 SQL Express 2008 R2 服务器返回相对大量的记录到 WCF 客户端。我的测试表目前包含大约 11.000 条记录。 LINQ 查询就像这样简单:

Database DB = new Database(); // create object context
var retValue = DB.Entities.Persons
        .Include("District")
        .Include("District.City")
        .Include("District.City.State")
        .Include("Nationality")

return retValue.ToList();

这大约需要 10 秒才能完成。

在 SQL Server Managament Studio 中执行相同的 SELECT 查询只需不到 1 秒。

EF 一定要这么慢吗?

最佳答案

您的查询并不简单,它包含大量联接(由于 Include),更重要的是它可能返回大量重复数据,特别是如果包含的导航属性是集合: https://stackoverflow.com/a/5522195/270591

耗时的部分是对象具体化以及当数据库结果返回到 Entity Framework 上下文时将实体附加到上下文。

您的测量(在问题的评论中)证实了这一点,即同一上下文中的第二个查询非常快。在这种情况下,EF 将对数据库执行查询,但不需要再次具体化对象,因为它们仍然附加到上下文。

如果您在第二个上下文中运行第二个查询,则生成的实体必须附加到新上下文 - 而此步骤又很慢(也由您的测量证实)。

与原始 SQL 查询相比,使用 EF 进行查询实际上可能很慢并且会增加大量开销。 EF 需要创建许多数据结构,为更改跟踪和管理上下文中的对象标识做好准备,这会消耗额外的时间。

我认为提高性能的唯一方法是禁用更改跟踪(假设您的操作不需要它)。在 EF 4.0/ObjectContext 中,它将是:

Database DB = new Database();
DB.Entities.Persons.MergeOption = MergeOption.NoTracking;
// MergeOption is in System.Data.Objects namespace

使用这种方法时,必须注意,即使相关对象具有相同的 key ,相关对象也将被创建为单独的对象 - 启用更改跟踪时情况并非如此,因为附加到上下文将避免这种重复。

因此,可能会有更多对象被加载到内存中。如果这会适得其反,并且实际上会进一步降低性能,或者它是否仍然性能更好,则需要进行测试。

关于entity-framework - EntityFramework : Calling ToList() on IQueryable with ~11. 000 条记录需要 10 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10009654/

相关文章:

SQL - 动态 SQL 查询将用分号 (;) 分隔的单列字符串转换为多列

c# - 如何告诉 Entity Framework 忽略数据库生成插入或更新的值?

postgresql - PostgreSQL Entity Framework 上的 RowVersion 实现

c# - 从 3.5 更新到 4.0 时出现 WCF 问题

entity-framework - EF 迁移 - 允许单次迁移丢失数据

.net - LINQ to SQL 还是经典的 ADO.NET?

SQL Server 2008 查询 - 查找不同表中两个不同列中不存在的电子邮件

c# - 有没有更好的方法来编写 new List<string> {"a", "b"}.Contains(str)?

c# - ASP.net Linq to SQL同时分组和添加?

sql-server - 在 SQL Server 中更新 XML 字符串时查询优化?