我想从SQL Express 2008 R2服务器返回相对大量的记录,通过EntityFramework 4到WCF客户端通过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中是否必须缓慢?
答案 0 :(得分:5)
您的查询不简单,它包含大量连接(由于Include
),更重要的是它可能会返回大量重复数据,特别是如果包含的导航属性是集合:{{3 }}
时间消耗部分是对象实现,并在数据库的结果返回到实体框架上下文时将实体附加到上下文。
这可以通过您的测量(在您的问题的评论中)确认在同一上下文中的第二个查询非常快。在这种情况下,EF将对数据库执行查询,但不需要再次实现对象,因为它们仍然附加到上下文。
如果在第二个上下文中运行第二个查询,则生成的实体必须附加到新上下文 - 此步骤再次变慢(也通过测量确认)。
这可能是EF 的查询实际上很慢并且与原始SQL查询相比增加了大量开销的一点。 EF需要创建许多数据结构,为变更跟踪和管理上下文中的对象标识做好准备,这会花费额外的时间。
我能看到改善性能的唯一方法是禁用更改跟踪(假设您不需要它来进行操作)。在EF 4.0 / ObjectContext
中,它将是:
Database DB = new Database();
DB.Entities.Persons.MergeOption = MergeOption.NoTracking;
// MergeOption is in System.Data.Objects namespace
使用这种方法时,必须要注意的是,相关对象将被创建为单独的对象,即使它们具有相同的密钥 - 这与启用的更改跟踪不同,因为附加到上下文将避免这种重复。
因此,可能会有更多对象加载到内存中。如果这会产生反作用,实际上性能会降低甚至更高,或者它仍然表现更好是一个测试问题。
答案 1 :(得分:0)
这很可能是因为与查询执行相比,查询编译(许多包含的LINQ查询 - >要使用的SQL)在EF中非常慢。您可以通过CPU分析代码来验证这是否是问题。考虑使用较少的包含+多个较小的查询,使用已编译的查询或升级到最新的EF5 beta。