I'm new to using ORM in dealing with database, Currently I'm making a new project and I have to decide if i'll use Entity Framework or Dapper. I read many articles which says that Dapper is faster than Entity Framework.
So I made 2 simple prototype projects one using Dapper and the other uses Entity Framework with one function to get all the rows from one table. The table schema as the following picture
and the code for both projects as the following
for Dapper project
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());
after trying the above code many times only the first time I run the project the dapper code will be faster and after this first time always I get better results from entity framework project I tried also the following statement on the entity framework project to stop the lazy loading
hrctx.Configuration.LazyLoadingEnabled = false;
but still the same EF performes faster except for the first time.
Can any one give me explanation or guidance on what makes EF faster in this sample although all the articles on the web says the opposite
Update
I've changed the line of code in the entity sample to be
IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();
using the AsNoTracking as mentioned in some articles stops the entity framework caching and after stopping the caching the dapper sample is performing better, (but not a very big difference)
There is no problem to mix them together. In my current project I'm using Dapper for selecting data and EF for creating and updating and database migrations.
Dapper becomes exteremely helpful when it comes to complex queries where more than two tables are involved or where there are some complex operations (joining by more than one column, joining with >= and <= clauses, recursive selections, cte's etc) where to use pure SQL is much easier than LINQ. As I know, Entity Framework (unlike Dapper) cannot use .FromSql() method on custom DTO's. It can map only one table that should be in your database context.
ORM (Object Relational Mapper) is a tool that creates layer between your application and data source and returns you the relational objects instead of (in terms of c# that you are using) ADO.NET objects. This is basic thing that every ORM does.
To do this, ORMs generally execute the query and map the returned
DataReader
to the POCO class. Dapper is limited up to here.To extend this further, some ORMs (also called "full ORM") do much more things like generating query for you to make your application database independent, cache your data for future calls, manage unit of work for you and lot more. All these are good tools and adds value to ORM; but it comes with cost. Entity Framework falls in this class.
To generate the query, EF have to execute additional code. Cache improves the performance but managing the cache needs to execute additional code. Same is true for unit of work and any other add-on feature provided by EF. All this saves you writing additional code and EF pays the cost.
And the cost is performance. As Dapper does very basic job, it is faster; but you have to write more code. As EF does much more than that, it is (bit) slower; but you have to write less code.
So why your tests show opposite results?
Because the tests you are executing are not comparable.
Full ORMs have many good features as explained above; one of them is UnitOfWork. Tracking is one of the responsibilities of UoW. When the object is requested (SQL query) for first time, it causes round trip to database. This object is then saved in memory cache. Full ORM keeps track of changes done to this already loaded object(s). If same object is requested again (other SQL query in same UoW scope that include loaded object), they do not do database round trip. Instead, they return the object from memory cache instead. This way, considerable time is saved.
Dapper do not support this feature that causes it to perform slower in your tests.
But, this benefit is only applicable if same object(s) loaded multiple times. Also, if number of objects loaded in memory is too high, this will slow down the full ORM instead as then the time required to check the objects in memory will be higher. So again, this benefit depends on use-case.
I read many articles which says that Dapper is faster than Entity Framework
The problem with the most of the benchmarks on internet is that they compare EF Linq to Dapper. And that's what you did too. Which is unfair. An auto generated query(EF) is often not equal to the one written by a good developer.
This,
should be replaced by this.
Edit:
As pointed out by @mjwills, below is the results table for
insert
,update
andselect
statements.Dapper is outperforming EF Core 2. However, it can be seen that for EF plain queries, the difference is very minimum. I have posted complete details here.
The article Entity Framework Core 2.0 vs. Dapper performance benchmark, querying SQL Azure tables confirms that Dapper is a bit quicker, but not enough to ignore "full ORM" benefits.