Skip to content

Instantly share code, notes, and snippets.

@ozzie-eu
Last active October 29, 2024 12:33
Show Gist options
  • Save ozzie-eu/6af55841cd34c44d894b4e0b469e298f to your computer and use it in GitHub Desktop.
Save ozzie-eu/6af55841cd34c44d894b4e0b469e298f to your computer and use it in GitHub Desktop.
.NET console application to compare EF Core and Dapper performance running against the Wide World Importers sample database.
using Dapper;
using Microsoft.EntityFrameworkCore;
using System.Data.SqlClient;
using System.Diagnostics;
namespace WideWorldImportersPerformanceBenchmark
{
public class WideWorldImportersContext : DbContext
{
public DbSet<Orders> Orders { get; set; }
public DbSet<Customers> Customers { get; set; }
public DbSet<OrderLines> OrderLines { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("CONNECTION_STRING"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("sales");
modelBuilder.Entity<Orders>()
.HasKey(o => o.OrderID);
modelBuilder.Entity<Customers>()
.HasKey(c => c.CustomerID);
modelBuilder.Entity<OrderLines>()
.HasKey(ol => new { ol.OrderID, ol.StockItemID });
modelBuilder.Entity<Orders>()
.HasOne(o => o.Customer)
.WithMany() // No navigation property in Customer
.HasForeignKey(o => o.CustomerID);
modelBuilder.Entity<OrderLines>()
.HasOne(ol => ol.Order)
.WithMany(o => o.OrderLines)
.HasForeignKey(ol => ol.OrderID);
}
}
public class Orders
{
public int OrderID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public Customers Customer { get; set; }
public List<OrderLines> OrderLines { get; set; } = new();
}
public class Customers
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
}
public class OrderLines
{
public int OrderID { get; set; }
public int StockItemID { get; set; }
public decimal UnitPrice { get; set; }
public int Quantity { get; set; }
public Orders Order { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
using var context = new WideWorldImportersContext();
using var connection = new SqlConnection(Environment.GetEnvironmentVariable("CONNECTION_STRING"));
await BenchmarkEFCore(context);
await BenchmarkDapper(connection);
}
static async Task BenchmarkEFCore(WideWorldImportersContext context)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var orders = await context.Orders
.Include(o => o.Customer)
.Include(o => o.OrderLines)
.ToListAsync();
stopwatch.Stop();
Console.WriteLine($"EF Core execution time: {stopwatch.ElapsedMilliseconds} ms");
}
static async Task BenchmarkDapper(SqlConnection connection)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var sql = @"
SELECT o.*, c.*, ol.*
FROM Sales.Orders o
INNER JOIN Sales.Customers c ON o.CustomerID = c.CustomerID
INNER JOIN Sales.OrderLines ol ON o.OrderID = ol.OrderID";
var orders = (await connection.QueryAsync<Orders, Customers, OrderLines, Orders>(sql,
(o, c, ol) =>
{
o.Customer = c;
o.OrderLines.Add(ol);
return o;
}, splitOn: "CustomerID, OrderID"))
.ToList();
stopwatch.Stop();
Console.WriteLine($"Dapper execution time: {stopwatch.ElapsedMilliseconds} ms");
}
}
}
@ozzie-eu
Copy link
Author

The program has dependencies on the following packages:

  • Dapper
  • Microsoft.EntityFrameworkCore.SqlServer
  • System.Data.SqlClient

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment