我是新手使用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());
for Entity Framework Project
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());
在我第一次运行项目后多次尝试上面的代码后,dapper代码会更快,在这第一次之后我总是从实体框架项目得到更好的结果 我还尝试在实体框架项目上使用以下语句来停止延迟加载
hrctx.Configuration.LazyLoadingEnabled = false;
但是,除了第一次以外,EF的表现仍然相同。
任何人都可以给我解释或指导什么使EF在这个样本中更快,尽管网上的所有文章都相反
更新
我已将实体样本中的代码行更改为
IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();
使用某些文章中提到的 AsNoTracking 会停止实体框架缓存,停止缓存后,dapper示例的效果会更好,(但差别不是很大)
答案 0 :(得分:29)
ORM(对象关系映射器)是一种在应用程序和数据源之间创建层的工具,它返回关系对象而不是 (就您正在使用的c#而言)ADO.NET对象。这是每个ORM都做的基本事情。
为此,ORM通常执行查询并将映射返回的DataReader
执行到POCO类。 Dapper在这里有限。
为了进一步扩展这一点,一些ORM(也称为#34;完整的ORM和#34;)做更多的事情,比如为您创建查询以使您的应用程序数据库独立,缓存数据以备将来调用,管理工作单元为了你和更多。所有这些都是很好的工具,为ORM增添了价值;但它带有成本。实体框架属于这一类。
要生成查询,EF必须执行其他代码。缓存可提高性能,但管理缓存需要执行其他代码。对于工作单元和EF提供的任何其他附加功能也是如此。所有这些都可以节省你编写额外的代码,EF支付费用。
成本是性能。由于Dapper做了非常基本的工作,它更快;但你必须写更多的代码。由于EF做的远远不止于此,它会慢一点;但你必须少写代码。
那么为什么你的测试显示相反的结果?
因为您正在执行的测试无法比较。
完整的ORM具有许多优点,如上所述;其中一个是UnitOfWork。跟踪是UoW的责任之一。首次请求对象(SQL查询)时,会导致数据库往返。然后将此对象保存在内存缓存中。完整ORM跟踪对此已加载对象所做的更改。如果再次请求相同的对象(在包含加载对象的同一UoW范围内的其他SQL查询),则它们不会执行数据库往返。相反,它们会从内存缓存中返回对象。这样可以节省大量时间 Dapper不支持此功能,导致它在测试中执行速度较慢。
但是,此优势仅适用于多次加载相同对象的情况。此外,如果内存中加载的对象数太多,这将减慢完整的ORM,因为检查内存中的对象所需的时间将更长。同样,这种好处取决于用例。
答案 1 :(得分:2)
I read many articles which says that Dapper is faster than Entity Framework
Internet上大多数基准测试的问题在于,它们将EF Linq与Dapper进行了比较。这也是您所做的。这不公平。自动生成的查询(EF)通常不等于优秀开发人员编写的查询。
这个
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
应替换为此。
IEnumerable<Employee> emplist = hrctx.Employees.FromSql(@"Select * From Employees").AsNoTracking();
编辑:
@mjwills指出,以下是insert
,update
和select
语句的结果表。
Dapper的性能优于EF Core2。但是,可以看出,对于EF普通查询,差异非常小。我已经发布了complete details here。
答案 2 :(得分:1)
文章Entity Framework Core 2.0 vs. Dapper performance benchmark, querying SQL Azure tables证实Dapper有点快,但不足以忽略“完全ORM”的好处。
答案 3 :(得分:1)
将它们混合在一起没有问题。在我当前的项目中,我正在使用Dapper选择数据,使用EF进行创建和更新以及数据库迁移。
当涉及到多个表或涉及一些复杂操作(通过多个列联接,使用> =和<=子句联接,递归选择,CTE等)的复杂查询时,Dapper极为有用。在哪里使用纯SQL比LINQ容易得多。据我所知,实体框架(与Dapper不同)不能在自定义DTO上使用.FromSql()方法。它只能映射应该在数据库上下文中的一个表。