Dej*_*vić 2 linq entity-framework sql-server-2008-r2 entity-framework-4 tolist
我想从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();
Run Code Online (Sandbox Code Playgroud)
这大约需要10秒钟才能完成.
在SQL Server Managament Studio中执行时,相同的SELECT查询所需的时间不到1秒.
在EF中它是否必须缓慢?
您的查询并不简单,它包含大量连接(由于Includes),更重要的是它可能会返回大量重复数据,特别是如果包含的导航属性是集合:https://stackoverflow.com/a/5522195/270591
时间消耗部分是对象实现,并且当数据库的结果返回到实体框架上下文时将实体附加到上下文.
这可以通过您的测量(在您的问题的评论中)确认在同一上下文中的第二个查询非常快.在这种情况下,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
Run Code Online (Sandbox Code Playgroud)
使用这种方法时,必须要注意的是,相关对象将被创建为单独的对象,即使它们具有相同的密钥 - 这与启用的更改跟踪不同,因为附加到上下文将避免这种重复.
因此,可能会有更多对象加载到内存中.如果这会适得其反,实际上性能下降甚至更多,或者它仍然表现更好是一个测试问题.