为什么实体框架在直接选择语句中比Dapper执行得更快

Ahm*_*med 27 c# entity-framework dapper

我是新手使用ORM处理数据库,目前我正在制作一个新项目,我必须决定是否使用Entity Framework或Dapper.我读了许多文章说Dapper比实体框架更快.

所以我使用Dapper创建了两个简单的原型项目,另一个使用Entity Framework和一个函数从一个表中获取所有行.表格架构如下图所示

表格式

以及两个项目的代码如下

对于Dapper项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Emp> emplist = cn.Query<Emp>(@"Select * From Employees");
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());
Run Code Online (Sandbox Code Playgroud)

实体框架项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());
Run Code Online (Sandbox Code Playgroud)

经过多次尝试上面的代码只有我第一次运行项目时,dapper代码会更快,在这第一次之后我总是从实体框架项目中获得更好的结果我还尝试了以下关于实体框架项目的语句来阻止懒惰装载

hrctx.Configuration.LazyLoadingEnabled = false;
Run Code Online (Sandbox Code Playgroud)

但是,除了第一次以外,EF的表现仍然相同.

虽然网上的所有文章都相反,但任何人都能给我解释或指导EF在这个样本中的速度更快

更新

我已经改变了实体样本中的代码行

IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();
Run Code Online (Sandbox Code Playgroud)

使用某些文章中提到的AsNoTracking会停止实体框架缓存,停止缓存后,dapper样本表现更好,(但不是很大的区别)

Ami*_*shi 35

ORM(对象关系映射器)是一种在应用程序和数据源之间创建层的工具,它返回关系对象而不是(就您正在使用的c#而言)ADO.NET对象.这是每个ORM所做的基本事情.

为此,ORM通常执行查询并将返回的映射映射DataReader到POCO类.小巧玲珑限于此.

为了进一步扩展这一点,一些ORM(也称为"完整ORM")可以执行更多操作,例如为您创建查询以使您的应用程序数据库独立,为将来的调用缓存数据,为您管理工作单元等等.所有这些都是很好的工具,为ORM增添了价值; 但它带有成本.实体框架属于这一类.

要生成查询,EF必须执行其他代码.缓存可提高性能,但管理缓存需要执行其他代码.对于工作单元和EF提供的任何其他附加功能也是如此.所有这些都可以节省编写额外代码的费用,EF 可以节省成本.

成本就是性能.由于Dapper做了非常基本的工作,它更快; 但你必须写更多的代码.由于EF做的远远不止于此,它会慢一点; 但你必须少写代码.

那么为什么你的测试结果反应相似?
因为您正在执行的测试无法比较.

如上所述,完整的ORM具有许多良好的特征; 其中一个是UnitOfWork.跟踪是UoW的责任之一.首次请求对象(SQL查询)时,会导致数据库往返.然后将此对象保存在内存缓存中.完整ORM跟踪对此已加载对象所做的更改.如果再次请求相同的对象(在包含加载对象的同一UoW范围内的其他SQL查询),则它们不会执行数据库往返.相反,它们会从内存缓存中返回对象.这样,节省了相当多的时间.
Dapper不支持此功能,导致它在测试中执行速度较慢.

但是,此优势仅适用于多次加载相同对象的情况.此外,如果内存中加​​载的对象数太多,这将减慢完整的ORM,因为检查内存中的对象所需的时间会更长.再次,这种好处取决于用例.

  • 其中一些是用棘手的 LINQ 解决的,而另一些只能用纯 SQL 解决。您花了很多时间来了解您可以使用 EF 做什么以及不可以做什么。项目的工作量越大,LINQ 查询就越低效,您也必须用纯 SQL 重写它们。然后你意识到你必须关闭它的默认自动跟踪器并使用一些第三方库,如 EntityFramework-Plus 以使其更快地工作。最后你觉得怎么了?为什么我选择了这个完整的 ORM 并花了很多时间来学习它,现在我只将它用于简单的查询?!然后你会找到Dapper。 (10认同)
  • @Sergey:`“然后你会找到 Dapper。”` 不错的选择。恕我直言,在某些场景中,全 ORM、微 ORM 和手写查询发挥了它们的作用并具有它们的重要性。设计决定使用什么以及我们应该从中得到什么。 (3认同)
  • 在编写复杂查询时,有时EF不会生成最佳SQL,而您仍然必须手动进行操作。因此,我不会说EF确实是“完整的”,它对非常简单的查询很有帮助,但是您必须充分了解它才能有效使用,并且还必须全面了解SQL,因此,您必须了解2大当您刚开始阅读有关EF的书时,它的主题就比预期的要多,而不是1。但是,日复一日,您一次又一次地面临新的挑战。 (2认同)

Moh*_*sin 5

I read many articles which says that Dapper is faster than Entity Framework

互联网上大多数基准测试的问题在于,它们将EF Linq与Dapper进行了比较。这也是您所做的。这不公平。自动生成的查询(EF)通常不等于优秀开发人员编写的查询。

这个,

IEnumerable<Employee> emplist = hrctx.Employees.ToList();
Run Code Online (Sandbox Code Playgroud)

应该用这个代替。

IEnumerable<Employee> emplist = hrctx.Employees.FromSql(@"Select * From Employees").AsNoTracking();
Run Code Online (Sandbox Code Playgroud)

编辑:

正如@mjwills指出的,下面是结果表insertupdateselect语句。

在此处输入图片说明

Dapper的性能优于EF Core2。但是,可以看出,对于EF普通查询,差异非常小。我已经在这里发布了完整的详细信息

  • EF Linq to Dapper 是最准确的比较。您知道有多少开发人员在使用 EF 时手工制作查询?Ef Linq to Dapper 是基于使用情况的苹果与苹果比较。 (6认同)