C# EF 4.1代码首先执行查询的速度比我的应用程序中的常规EF慢3倍

C# EF 4.1代码首先执行查询的速度比我的应用程序中的常规EF慢3倍,c#,.net,entity-framework,entity-framework-4,entity-framework-4.1,C#,.net,Entity Framework,Entity Framework 4,Entity Framework 4.1,我有一个宠物项目(一个简单的论坛应用程序),我用它来测试所有最新的.NET技术,最近我开始先玩弄实体框架代码。此应用程序已经有一个现有EF解决方案,其中一个EDMX文件映射到现有数据库,并且所有“我的实体”都是自动生成的。到目前为止,这个解决方案效果很好 注意:请记住,对EF 4.1的更改纯粹是为了学习。如果你想知道我的需求是什么导致了我升级,那就没有了。我只是想好玩 我复制了这个项目并进行了升级,因此我将拥有相同的项目,但使用不同的实体框架实现。在新项目中,我使用一个名为Entity Fram

我有一个宠物项目(一个简单的论坛应用程序),我用它来测试所有最新的.NET技术,最近我开始先玩弄实体框架代码。此应用程序已经有一个现有EF解决方案,其中一个EDMX文件映射到现有数据库,并且所有“我的实体”都是自动生成的。到目前为止,这个解决方案效果很好

注意:请记住,对EF 4.1的更改纯粹是为了学习。如果你想知道我的需求是什么导致了我升级,那就没有了。我只是想好玩

我复制了这个项目并进行了升级,因此我将拥有相同的项目,但使用不同的实体框架实现。在新项目中,我使用一个名为Entity Framework Power Tools的Visual Studio扩展从现有数据库生成POCO和DbContext。一切工作都完美无缺。我在大约30分钟内完成了应用程序的编译。非常令人印象深刻

但是,我现在在运行应用程序时注意到,查询执行速度比以前慢了大约3倍。你知道我会错过什么吗

以下是两种解决方案的详细信息,以及两种方案的LINQPad测量。(单击图像查看完整尺寸)

EF 4.0详细信息 下面是我的EF4.0数据模型的快照。它在顶部和底部切断了一些实体,但你明白了

下面是针对我的EF 4.0数据模型的LINQPad测试

请注意,执行查询需要2.743秒

环境足迹4.1详情 下面是我的EF4.1数据模型的快照。因为它只是代码,所以我将为一个实体和一个实体本身显示DbContext类以及一个映射类(fluent API代码)

DbContext TopicMap(fluent API配置) 主题(POCO实体) 下面是针对我的EF 4.1模型的LINQPad测试

请注意,这一次执行查询需要6.287秒,并且是完全相同的查询。它第一次运行时需要超过30秒。如果转到LINQPad中的SQL和IL选项卡,则生成的SQL和IL代码对于这两种数据模型都是相同的。这真让我伤心。在实际应用中,EF4.1的速度非常慢,无法使用

我对这两个模型运行了相同的LINQ查询。该查询获取普通论坛用户的所有主题,按其最后回复日期(如果没有回复,则按主题发布日期)降序排列

显然,我可以回到EF 4.0,继续我的快乐生活,但如果我错过了什么,我真的很感兴趣。

更新 由于最近的一些发展,我完全重新审视这个答案

由于微软实体框架团队的一些询问试图复制我的问题,我回到过去,重新开始我的步骤,以更好地帮助缩小问题的范围。我问这个问题已经有一段时间了,我现在比当时更了解事情

我决定从头开始,做一个简单的测试项目,而不是回去尝试运行一些非常旧的代码。我把一个简单的数据库和两个表放在一起,并将它们映射到EF4.0设计器文件

这将生成如下所示的连接字符串:

<add name="EFTestEntities" connectionString="metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=EFTest;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<add name="EFTestContext" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=EFTest;Integrated Security=True;Pooling=False" />
扩展以生成我的模型对象和DbContext。我唯一修改的是连接字符串,以删除项目中存在设计器文件时引用的元数据,因此它看起来如下所示:

<add name="EFTestEntities" connectionString="metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=EFTest;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<add name="EFTestContext" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=EFTest;Integrated Security=True;Pooling=False" />

然后,我运行了与设计器完全相同的查询

除了代码首先生成映射元数据所需的稍微额外的时间外,查询时间没有差异。在那个初始查询之后,两个版本的EF执行的几乎相同。我正要解决这个问题,因为它是不可复制的,但是我注意到我在这个问题上做了一些可怕的事情。我在查询之前调用了
.AsEnumerable()
。如果您还不知道它的作用,那么将导致整个实体集合被拉入内存,然后查询将作为LINQ应用于对象,而不是LINQ应用于实体

这意味着我把一整张桌子都吸进了内存,然后在那里对它执行LINQ。如果SQL server与您的网站位于同一台计算机上,您可能不会注意到差异,但在许多情况下,这将是一个巨大的问题。在我的案例中,它确实造成了性能损失

我回到我的测试中,在查询之前放置了
.AsEnumerable()
,然后运行它们

现在我预计时间会慢一些,因为我的LINQ查询没有被转换成表达式树并在数据库中执行。然而,我似乎在我的问题中重复了这个问题。纯代码版本的返回速度要慢得多。这实际上很奇怪,因为它们应该运行相同的程序。我并不奇怪它们的运行速度比查询针对IQueryable时慢,但是现在它们针对的是IEnumerable,这两者之间有很大的区别。通过向表中添加越来越多的数据,我能够扩大两者之间的差异

我继续向数据库添加了5000多个主题,每个主题有30个回复。因此,现在总共有6000个主题行和165000个回复行。首先,我使用适当的LINQ to实体运行查询:

正如你所看到的,仍然没有区别。然后,我使用
.AsEnumerable()
对LINQ to对象运行查询


我在三次查询后停止了它,因为每次查询等待大约两分钟是非常痛苦的。在我的问题中,我似乎无法产生3倍于我在问题中所展示的速度慢的问题,但代码的速度要慢得多。EDMX方法完成一个查询只需要不到两分钟的时间,而纯代码方法始终需要两分钟的时间。

如果我没有误解,您有两种情况,并且在这两种情况下比较