Dapper is a lightweight tool that is developed by the StackOverflow developer team as a micro-ORM. On the other hand, Entity Framework is one of the most popular ORM tools among Dotnet developers. It is not a micro-ORM. Thus, it covers tons of features that an ORM has to have which is why I think it is wrong comparing those two. In this story, you will see some Benchmark results from a project that I built. These benchmark results will be calculated by a very famous and successful tool named “BenchmarkDotNet”. If you don’t know what it is, you may visit here.
The Project Definition
This project will hold 7 different test categories and each category has different types of tests related to its category by comparing Dapper and EF. Joined table queries will not be tested in this project. Tests are; Insert, InsertMany, Update, Select, Search, Function, Delete
Project Side; This is a Console App in NET6. Dapper Side; Dapper v2.0, Dapper.FluentMap v2.0, Dapper.FluentMap.Dommel v2.0.
I must admit as an EF user for years that exploring the Dapper and its mapping features was really difficult for me as it has different extension libraries some of which have lack some important features. Whenever I changed the extension library to use, I faced some problems. However, as EF has everything built-in, it was easier to manage.
EF Side; Entityframework has a version of 6.0.
Data Generation Side; To generate fake data to process, the Bogus tool will be used here.
Database Side; The DB is used within this project is SqlServer 2019(x64). It will be running in a container on my local Docker Desktop, on Windows. We have a Student table which is like;
Student Table DDL
Important Notes Before Starting
In this project, we are to test the features that both have in common. Dapper has many different extension libraries which give it new features. However, I didn’t want to use every single library in this project. I just tried to use the useful once. Using other libraries might change the benchmark results. On the other hand, to create a fair comparison environment, the same model is used for both Dapper and EF with the same mapping features. As we are testing their most common features, creating the connection will not be involved in this project as they can be held differently by the environment they are working. For instance, creating the DbContext of EF might be handled by dependency injection of a .Net Core WebAPI project whereas SqlConnection might be created by any sort of ConnectionPool. In test methods, I’ll be using a single Connection/DbContext and all the tests will use these two.
Dapper was almost always so fast whereas EntityFrameworks had times that it had problems with performance. However, with every new version of the .NET framework, it has speeded up. In this story, we’ll be seeing some results to very close each other. With EF7, it will probably have better performance.
In this test, we’ll be testing both built-in insert and raw SQL Query methods for both Dapper and EntityFramework. As we have InsertMany test, we are just inserting a single row to the table. The single row insert test is completed and the results are like; After inserting, our table would have 4040 records.
Single Insert Test Result
As the result demonstrates Dapper is slightly faster here. We can see the difference for the built-in method is more than the raw SQL insert. Memory management is also better by Dapper. However, I want to draw your attention to outliers, which represent the stability of the ORM. As it seems, EF has fewer outliers than Dapper, which we may admit that EF has stable behavior here.
Single Insert Outliers
Insert Many Test
In this test, we will be testing the built-in multiple rows insert methods. Even though both Dapper and EF have 3rd-party libraries for BulkInsert, we will not be using any libraries here. To simulate multiple inserts, the record count will be sent as 10, 100, and 1000 as parameters by the test library. We will be seeing the results for all of the parameters. After the test is completed, the record count in the table would be 126140.
Insert Many Results
We have a different story here. In all 3 iterations, EF looks faster. As the row count increases, the performance difference increases. Especially, while inserting 1000 records, the difference goes significantly big. Dapper’s performance for big numbers looks very bad.
In the update test, we will be testing both the build-in update method and also raw SQL method like we had on “Insert Test”. On initialization of the test, we’ll be getting random IDs from databases and using this ID to update the records. We are doing it in initialize method to avoid the latency of updating process. Both Dappers and EFs update method works the same, which gets the data to memory — update the record and make the changes on DB. We replaced students' first names with the upper versions of them. For raw SQL updating, we are replacing the “FirstName” with “XXX”.
When EF is slightly faster for raw SQL updating, on the built-in update method Dapper looks faster. Memory management is also held better by Dapper. Let’s look at how the outliers are shaped. On the outliers, Dapper has less stability on raw SQL updates.
In Select Test, we will be testing vary of selection methods all of which are built-in methods. Let’s look at the results.
The results show us that all the methods except the “Get ALL” have almost the same performance. For most of the results, memory allocation is better on the Dapper side. EF has a better result on SingleOrDefault, Filter By FirstName with raw SQL whereas Dapper is better on Find, Filter By FirstName with LinQ.
In the search test, we will be testing maybe the most popular kinds of usage of ORM. As we mostly filter the data on the database, filter features of the ORMs become more important. Let’s look at the results.
We have equal, StartsWith, Contains, and Between test methods. In addition, using EF gives us chance to use Database-defined methods. On the results, you may see the usage of this feature on the results ends with “F”. As we see on the table, EF has better performance on most of the tests. Especially with the database-defined methods(EF.Functions). Except for the between method, memory allocations look the same. The biggest difference is in searching the records with starts with “A”.
In this test, we will be testing aggregate functions such as Total Count, Paged Results, etc. Let’s look at the results.
Dapper has slightly better performance on three tests. Memory management is also handled better by Dapper. On the outliers table, EntityFramework looks more stable than Dapper.
In the delete test, we will use the same way of testing that we used in Update. Caching the Students in memory to delete later. Let’s look at the results.
The same result again. The built-in delete has been handled with better performance by Dapper whereas EntityFramework is slightly better at deleting the row by raw SQL. Dapper is again better at memory allocation.
Resource: Medium - Salih Cantekin
The Tech Platform