Dapper vs Entity Framework Core: Which Should You Use in .NET?
Dapper and Entity Framework Core are the two most popular ways to talk to SQL Server from .NET. Debates about them often turn into speed contests, but the better question is: how much do you want to write SQL yourself, and how much do you want the framework to do for you?

Dapper in one minute
Dapper is a "micro-ORM": a small library of extension methods on IDbConnection. You write the SQL; Dapper runs it and maps the results to your objects.
using var conn = new SqlConnection(connectionString);
var employees = await conn.QueryAsync<Employee>(
@"SELECT EmployeeId, FullName, DepartmentId
FROM dbo.Employee
WHERE DepartmentId = @DeptId AND IsActive = 1",
new { DeptId = deptId });Parameters are passed as an anonymous object, so queries stay safe from SQL injection.
EF Core in one minute
EF Core is a full ORM. You describe your model in C#, write LINQ, and EF Core generates the SQL, tracks changes and saves them, with migrations to evolve the schema.
var employees = await db.Employees
.Where(e => e.DepartmentId == deptId && e.IsActive)
.Select(e => new { e.EmployeeId, e.FullName, e.DepartmentId })
.ToListAsync();Side-by-side
| Dapper | EF Core | |
|---|---|---|
| Who writes the SQL | You | EF Core (from LINQ) |
| Raw overhead | Very low | Low to moderate; close to Dapper for well-written, no-tracking queries |
| Change tracking | No | Yes |
| Relationships and loading | Manual (multi-mapping) | Built in (Include, navigation properties) |
| Schema migrations | Separate tool | Built in |
| Learning curve | Small, if you know SQL | Larger: tracking, loading strategies, generated SQL |
| Complex SQL (CTEs, window functions, hints) | Easy: it is just SQL | Possible via raw SQL, less natural |
Choose Dapper when
- Your team is strong in SQL and wants full control of every query.
- The work is read-heavy: reports, dashboards, search screens, APIs returning projections.
- You work mostly with stored procedures or an existing database you do not own.
- You need hand-tuned queries with hints, CTEs or window functions.
Choose EF Core when
- You build a domain-rich application with lots of create, update and delete logic.
- You want migrations, relationships and change tracking out of the box.
- Developer productivity and maintainability matter more than squeezing every microsecond.
- You are happy to learn its performance habits: no-tracking reads, projections and checking generated SQL.
The pragmatic answer: use both
Many production systems use EF Core for everyday CRUD and business logic, and Dapper (or EF Core's raw SQL methods) for a handful of heavy reports and performance-critical queries. They can share the same connection string, and even the same connection:
var conn = db.Database.GetDbConnection(); // EF Core's connection
var rows = await conn.QueryAsync<PayrollSummary>(sql, new { RunId = runId });If both must take part in one transaction, pass EF Core's current transaction to Dapper as well (for example, db.Database.CurrentTransaction?.GetDbTransaction()).
Performance is mostly about the SQL
Whichever you choose, a missing index or an N+1 pattern will cost far more than the difference between the libraries. Look at the SQL that actually runs, check execution plans for slow queries, and fetch only the columns and rows you need.
Related reading:
Comments
Post a Comment