Using Dapper over EntityFramework for database operations in .NET Core
Tags: dotnet, database, performance, sql
Published: 2021-06-28 17:15:58

> We’re entering a new world in which data may be more important than software.
> --Tim O’Reilly

In most of the use cases for today’s software, data access plays an important role.
.NET core supports multiple framework options to store and access data in your software application may it be a microservice or a web application.

**Entity Framework Core** is one of the most recommended options suggested for applications working with relational database. [EF Core](https://docs.microsoft.com/en-us/ef/core/) is an object-relational mapper(ORM) that enables .NET developers to persist objects to and from a data source. It eliminates the need for most of the data access code developers would typically need to write.

**Dapper** is a simple object mapper for .NET and owns the title of **King of Micro ORM** in terms of speed and is virtually as fast as using a raw ADO.NET data reader. [Dapper](https://github.com/DapperLib/Dapper) operates directly using the IDbConnection interface which is extended by database providers like SQL Server, Oracle, MySQL etc. for their database.

Dapper is known for its high performance and is especially used by developers when they want to write the SQL query themselves with optimal performance or use stored procedures.
But how fast is it compared to EF Core?

To figure this out, as always, I have created a demo project [here](https://github.com/chaitanya-suvarna/efcore-dapper-benchmark) that compares the same read and write operations between EF Core and Dapper using [BenchmarkDotNet](https://benchmarkdotnet.org/index.html). I have used SQL Server as the relational database to insert and retrieve data.

##Structure of the database
For this demo, I have created two tables called `Athletes` and `Sports`. Before the execution of the benchmarks, I am also clearing down the database and reseeding the data with 16 records in `Athletes` and 5 records in `Sports`.

![Athletes table structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j856ph7p9sntvfzo69ag.png "Athletes table structure")

![Sports table structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mp80rc0m4l2sh392qoae.png "Sports table structure")

##Read Operation

I have created repository methods for EFCore and Dapper each to fetch data from the database. I have used the same criteria for both, which is to fetch the names of all indoor sport athletes older than 25 years of age.

{% gist https://gist.github.com/chaitanya-suvarna/45ede61b1498bf2be4f553a73e6663f4 %}

##Write Operation

I have created repository methods for EFCore and Dapper each to insert Athlete data into the database. I have used the same data to be inserted in both the methods.

{% gist https://gist.github.com/chaitanya-suvarna/6ee5c29064739ae30e464a4aa5455db3 %}

##Performance benchmarks for read and write

I have used BenchmarkDotNet to benchmark the performance for the database read and write operations using both EF Core and Dapper.

**BenchmarkDotNet** helps you to transform methods into benchmarks, track their performance, and share reproducible measurement experiments. The results for these benchmarks are presented in a user-friendly form that highlights all the important facts about your experiment.

I have set the iteration count as **100 iterations**. This can be configured by assigning the desired value to the variable numberOfIterations.

{% gist https://gist.github.com/chaitanya-suvarna/ab9237c10fdd6c87165c72f44fcb1c54 %}

##Benchmark results

On running the benchmark project, the below summary is what is displayed as output which shows that for **Dapper both read and write are faster, almost x2 times**, than EF Core for the same kind of operation.

The summary also shows that the memory allocated for Dapper operations is far less than the memory allocated for EF Core operations.

![Benchmark summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmuibshxujygl230o4a8.png "Benchmark summary")

The detailed results for both the read and write operations give detailed statistical information for the benchmark. It also gives a histogram for the the time interval for the database operation. BenchmarkDotNet also allows the measured data to be exported in different formats including plots.

![Detailed summary for read operations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pl9hazxvktr6mmegm5pw.png "Detailed summary for read operations
")

![Detailed summary for write operations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vhx6tb1wf1sj6cl5a31r.png "Detailed summary for write operations")

While benchmark results clearly state that Dapper has a higher performance than EF Core for both read and writes, **in most instances the performance for database writes is almost comparable**. Due to this, some developers prefer to use Dapper for read operations and EF Core for write operations involving complex objects to be written into the database as transforming them into Dapper queries itself may be a cumbersome task.

Dapper is safe from SQL injection with the use of parameters using anonymous objects and also allows you to use custom queries with performance enhancement which gives you better control over the database operations for eg. using `with(nolock)` in select queries.

Thus we have seen why Dapper is known as King of Micro ORM and how in our example, BenchmarkDotNet helped us showcase that it has a better performance to EF Core. It is important to note that the performance of both EF Core and Dapper vary based on the use case and the type of database operations being performed, but **Dapper in general performs better with database read operations**.

You can find my demo project that I have created to run this benchmark on my github repo here [https://github.com/chaitanya-suvarna/efcore-dapper-benchmark](https://github.com/chaitanya-suvarna/efcore-dapper-benchmark)

I hope you found this interesting and useful.

Thank you for reading!