需要重点指出的是,当一个抽象层或者类似EDM(译注:指Entity Data Model)的模块被用来转换数据库的关系样式时,会带来一定的性能损失。
查询与结果
本文使用了NorthWind数据库作为模型,并创建了一个简单查询:
(NorthwindEntities ne = NorthwindEntities()) { (Order o ne.Orders) { i = o.OrderID; } }
测试时,我们的每个查询对整个848行数据进行了10次遍历。结果很有意思,第1次运行时耗费了4241毫秒,而接下来的每次运行则平均耗费13毫秒左右的时间。最耗时的一部分内容是ObjectContext的创建,而在执行任意一个访问数据库的操作时,都会有一些耗时的操作发生。
(PerformanceArticleContext ne = PerformanceArticleContext()) { ObjectQuery<Orders> orders = ne.CreateQuery<Orders>(); (Orders o orders) { i = o.OrderID; } }
第一次运行该查询耗时179毫秒,但下一次运行则只耗费了15毫秒的时间。首次运行与后续运行在执行方面的区别在于它构建了能够为执行传递provider的命令树(command tree)。
LINQ查询在执行方式上与Entity SQL查询相似。例如,下面的查询:
(PerformanceArticleContext ne = PerformanceArticleContext()) { var orders = from order ne.Orders select order; (Orders o orders) { i = o.OrderID; } }
首次执行LINQ查询耗时202毫秒,而随后的执行耗时18毫秒,两者的差距还要低于Entity SQL。可以看到,使用编译了的LINQ查询对于性能的提高更为明显。编译LINQ查询的好处在于它构建了表达树(expression tree),当查询被编译时,后续的执行就不需要重建表达树了。编译的LINQ查询代码看起来像这样:
Func<PerformanceArticleContext, IQueryable<Orders>> compiledQuery = CompiledQuery.Compile((PerformanceArticleContext ne) => (from o ne.Orders select o)); (PerformanceArticleContext ne = PerformanceArticleContext()) { (Orders o compiledQuery(ne)) { i = o.OrderID; } }
注意,PerformanceArticleContext是一个委托。对于编译了的LINQ查询而言,第一次执行耗时305毫秒,而随后的执行时间则为15毫秒。结果并不惊人,值得关注的是编译的LINQ查询比之常规方式的LINQ查询,执行时间少了3毫秒。或许对于几个查询而言,这算不上什么,但如果有数以千计的查询,这样的性能提升就倍显价值所在了。作者: tznktg 时间: 2008-10-31 11:13 标题: 挖掘ADO.NET Entity框架的性能 ADO.NET团队建议开发人员在查询中应谨慎使用Track/NoTrack选项: