Entity Framework Core 2 Vs Dapper Performance Benchmark

2 min read

Motivation:

Working in a company where Microsoft technology stack is used widely. We chose .NET Core 2 for our new applications. Started researching which is better Entity Framework Core OR Dapper. Found this interesting performance benchmark but noticed that its unfair to compare Auto-generated SQL(EF) with human written SQL(Dapper). A more fair comparison would be to use same SQL for both. So decided to benchmark it on our own for the below use cases. Including linq vs Plain Queries comparisons and also the affect of AsNoTracking().

Use Cases:
  1. Select 5000 rows out of 500k rows.
  2. Insert new row.
  3. Update a row column at index 5001.

Source Code:

You can download the source code from git.

Test Environment:

  1. A SQL database server which is on LAN
  2. A table containing 500k rows and 50 columns.
  3. .Net Core 2 Console Application.
Nugets:
  1. Benchmark.NET
  2. Dapper
  3. Entity Framework Core 2

Results Table:

Use Case# Query Type ORM Linq/Plain .AsNoTracking() Applied Time Fastest
1. Select

5k rows from 500k

Dapper N/A N/A 129.2 ms  

 

Dapper

 

EF Core 2

Linq Yes 137.1 ms
Linq No 148.1 ms
Plain SQL Yes 132.6 ms
Plain SQL No 149.2 ms
2. Insert

new row

Dapper N/A N/A 5.423 ms  

Dapper

 

Ef Core 2

Linq No 16.20 ms
Plain SQL No 5.645 ms
3. Update

Row at 5001 index

Dapper N/A N/A 4.438 ms  

Dapper

Ef Core 2 Linq No 4.718 ms
Plain SQL No 4.652 ms

Dapper is clearly outperforming Entity framework Core 2 in above use cases.

But notice that Entity Framework Core 2’s plain sql commands are almost giving the same result as Dapper(very little difference). Also notice that AsNoTracking(), when applied gives faster response.

Let’s see the code for first use-case.

Dapper.Net Repository

Dapper’s query looks like this.Dapper.Net Repository

public class DapperRepository
    {
        public List GetUsersWithDapper()
        {
            using (IDbConnection db = new SqlConnection(@"Server=192.168.112.20\SQLEXPRESS;Database=DBName;User Id=sa;Password=password;Trusted_Connection=false;"))
            {
                return db.Query
                ($"select top 5000 * from users_general").ToList();
            }
        }
    }

Entity Framework Core 2 Repository

public class EFRepository
    {
        public List GetUsersWithEF()
        {
            using (var db = new EFCore2TestContext())
            {
                return db.UsersGeneral.FromSql("Select top 5000 * from users_general").AsNoTracking().ToList();
                //return db.UsersGeneral.Take(5000).AsNoTracking().ToList();
            }
        }
    }

Notice that i used AsNoTracking() for performance hit. As it will indicate EF not to track the models for change.

Benchmark Class

 public class EFCore2VsDapper
    {
        EFRepository _EFRepo;
        DapperRepository _DapperRepo;
        ADORepository _adoRepository;

        public EFCore2VsDapper()
        {
            _EFRepo = new EFRepository();
            _DapperRepo = new DapperRepository();
            _adoRepository = new ADORepository();
        }

        [Benchmark]
        public List GetUsersWithEntityFramework() => _EFRepo.GetUsersWithEF();

        [Benchmark]
        public List GetUsersWithDapper() => _DapperRepo.GetUsersWithDapper();

        //[Benchmark] Uncomment if you want to add ADO.NET to the competition
        //public List GetUsersWithADO() => _adoRepository.GetUsersWithADO();
    }

Run It!

 class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run(typeof(EFCore2VsDapper));

            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }
Caution:

Always run your code in release mode for performance benchmarks. Running a code in Debug mode can be 10x slower. So, publish it, got to the published directory and run the below command in cmd.

dotnet EFCore2VSDapper.dll

Benchmark.Net will execute your methods multiple times and will calculate average time taken. e.g below

Conclusion:

Dapper is faster than the Entity Frame Core 2. If performance is your biggest concern, Use dapper! However, if you want speedy development and can compromise a little bit on performance, use entity framework instead.

So, don’t select either based on my benchmark. You can download the source code and it is highly recommended to test it yourself for different scenarios before making a decision.

I’m missing something? or your tests gave different results? let me know by sharing your valuable feedback.

Thanks for reading. If you enjoyed this article, feel free to hit that clap button 👏 to help others find it.

3 Replies to “Entity Framework Core 2 Vs Dapper Performance Benchmark”

  1. @Bret! Thanks for response! I have tested it for Linq as well, it performs at same level or sometimes even better if we are pulling data from one table only. However, in case of joining from multiple tables or getting child objects along with parents, it get’s slows than stored procedure. So, it varies from scenario to scenario, i recommend to download and play with the above source code.
    Thanks 🙂

  2. @Bret! I have added a results table which shows performance comparison between Linq to PlainSql in EF. Please refer to the table above.
    Thanks 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *