我想通过 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/