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:
- Select 5000 rows out of 500k rows.
- Insert new row.
- Update a row column at index 5001.
Source Code:
You can download the source code from git.
Test Environment:
- A SQL database server which is on LAN
- A table containing 500k rows and 50 columns.
- .Net Core 2 Console Application.
Nugets:
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.
This is interesting, I would also like to see an Example using Linq to see what the overhead of Linq is in this scenario as well
@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 🙂
@Bret! I have added a results table which shows performance comparison between Linq to PlainSql in EF. Please refer to the table above.
Thanks 🙂