Dapper vs EF Core in .NET: Which ORM Should Your Team Use in 2026?

Choosing between Dapper and EF Core is one of the most common data-access decisions .NET teams face. Both tools solve the same fundamental problem β getting data in and out of a relational database β but they take radically different approaches. EF Core is a full-featured ORM that abstracts away SQL and manages your schema. Dapper is a micro-ORM that hands you back the SQL wheel and just maps the results. Neither is universally better, but one is almost certainly better for your team, right now.
π Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. π https://www.patreon.com/CodingDroplets
What Is EF Core?
Entity Framework Core is Microsoft's official ORM for .NET. It gives you a code-first or database-first workflow, a LINQ-based query API, change tracking, database migrations, and relationships β everything a full ORM promises. Since .NET Core, EF Core has been continuously improved for performance and flexibility, including compiled queries, raw SQL interpolation, bulk execution via ExecuteUpdate and ExecuteDelete, and the new HybridCache integration in .NET 9/10.
EF Core fits naturally into the standard ASP.NET Core service layer. You model your domain in C# classes, configure relationships via the Fluent API or data annotations, and let the framework translate your LINQ expressions into SQL. Migrations keep your database schema in sync with your model, and change tracking means you rarely have to think about INSERT vs UPDATE β EF Core figures it out.
The trade-off is abstraction overhead. EF Core generates SQL from your LINQ queries, and for complex queries that overhead can become visible. There are also footguns β lazy loading, N+1 queries, and unconstrained Include chains β that bite teams that don't know what to look for.
What Is Dapper?
Dapper is a micro-ORM created by the Stack Overflow team and open-sourced by Sam Saffron. It extends IDbConnection with a handful of generic extension methods (Query<T>, Execute, QueryMultiple) that map SQL results directly to C# objects. That's essentially all it does β and it does it extremely well.
You write the SQL. Dapper runs it and maps the result. No abstraction layer, no change tracking, no migration engine. What you get is near-raw ADO.NET performance with a dramatically better developer experience for result mapping.
Dapper is particularly popular in read-heavy microservices and reporting pipelines where query control matters more than domain modeling. It pairs well with Stored Procedures, complex multi-join reads, and scenarios where the DBA owns the SQL.
Side-by-Side Comparison
| Dimension | EF Core | Dapper |
|---|---|---|
| Type | Full ORM | Micro-ORM |
| Query model | LINQ / Fluent | Raw SQL |
| Performance | Good (excellent with tuning) | Near-raw ADO.NET |
| Schema migrations | Built-in (dotnet ef migrations) |
Manual / external tool |
| Change tracking | Yes | No |
| Relationships | Navigation properties, lazy load | Manual joins |
| Learning curve | ModerateβHigh | Low |
| SQL control | Partial (Raw SQL possible) | Full |
| Tooling & scaffolding | Excellent | Minimal |
| Community & support | Microsoft-backed, large | Community, Stack Overflow heritage |
| Complex query risk | N+1, over-fetching, cartesian explosion | You own the SQL, so you own the bugs |
| Team SQL proficiency required | Low | High |
Performance: How Big Is the Gap?
The Dapper vs EF Core performance debate is frequently exaggerated. In most real-world enterprise APIs β where queries run against an indexed relational database over a network β the round-trip time dwarfs any ORM overhead. You will not feel the difference on a standard CRUD endpoint.
The gap becomes meaningful in two scenarios:
- Very high-throughput endpoints (thousands of requests per second, tight SLAs) where EF Core's change tracking and query compilation overhead accumulates
- Complex batch read operations where EF Core generates inefficient SQL from LINQ β especially multi-level
Includechains on large result sets
EF Core has significantly closed the gap with compiled queries, AsNoTracking() reads, and the ExecuteUpdate/ExecuteDelete bulk path. For the vast majority of endpoints, a well-tuned EF Core query with AsNoTracking is within a few percent of Dapper.
The rule of thumb: start with EF Core. If profiling reveals a data-access bottleneck on a specific hot path, drop to Dapper (or raw SQL via FromSqlRaw) for that path only.
Migrations: EF Core Wins Decisively
Dapper has no migration story. You manage schema changes through SQL scripts, DbUp, Flyway, or whatever your team standardises on. That is not necessarily bad β many DBAs prefer owning schema changes directly β but it means more coordination overhead and no code-first schema evolution.
EF Core's migration system is production-grade. You model changes in C#, generate a migration, review the generated SQL, and apply it. The migration history table prevents double-application. In CI/CD pipelines, dotnet ef database update or the programmatic MigrateAsync() API integrates naturally.
For teams with a DBA-controlled schema, Dapper's lack of migrations is a feature. For teams that want schema and code in the same repository with the same lifecycle, EF Core's migrations are hard to beat.
When Should You Use EF Core?
EF Core is the right default for most .NET enterprise teams. Use it when:
- You are building a domain-rich application with complex relationships (orders, customers, line items, workflows)
- Your team has mixed SQL proficiency and you want productivity over control
- You need schema migrations colocated with your application code
- You are building CRUD-heavy services with moderate throughput (APIs, admin panels, back-office tools)
- You want change tracking and the ability to detect and persist changes without manual SQL
- You value long-term maintainability β EF Core code is generally more readable and refactoring-friendly than raw SQL strings
When Should You Use Dapper?
Dapper is the right choice when SQL control and performance matter more than productivity. Use it when:
- You are building read-heavy reporting or analytics endpoints where you already know the SQL
- The team has strong SQL skills and prefers writing queries rather than translating LINQ
- You are working with a DBA-managed schema and your application only reads/writes β no migrations needed
- You need to run complex stored procedures and map multi-result sets efficiently
- You have proven performance bottlenecks on specific data-access paths and raw throughput is required
- You are building a lightweight microservice with minimal domain logic and no schema ownership
Is Using Both at Once Viable?
Yes β and this is how many mature .NET teams operate. The hybrid approach is well-established:
- Use EF Core as the default for domain operations: inserts, updates, deletes, relationship navigation, migrations
- Drop to Dapper for read-heavy paths: reporting queries, paginated list endpoints, aggregation pipelines, anything where you have already written and optimised the SQL
Both can share the same IDbConnection/IDbContextFactory infrastructure. Dapper talks directly to the DbConnection inside your DbContext. The two tools coexist cleanly, and teams gain the best of both: EF Core's productivity for writes and schema management, Dapper's control and speed for complex reads.
What Does the SERP Miss?
Most comparison articles focus on performance benchmarks without addressing team and org-level factors β which often matter more than raw query speed:
- Onboarding cost: junior developers ramp up on EF Core far faster than on Dapper, because they do not need SQL expertise
- Refactoring safety: LINQ queries refactor with your model; SQL strings in Dapper do not
- Testability: EF Core's in-memory and SQLite providers make integration testing easier; Dapper tests depend on a live database or heavy mocking
- Audit and compliance: EF Core interceptors make it easy to add query logging, auditing, and soft-delete globally; Dapper requires manual SQL discipline
Choosing Dapper purely for performance without addressing these factors can create a long-term maintenance burden that dwarfs any throughput gain.
Recommendation: Which Should Your Team Use?
Default to EF Core. It is Microsoft's supported data-access layer for .NET, it solves the schema migration problem, and it scales to production just fine with proper tuning. Most teams that "switched to Dapper for performance" did so because they had N+1 bugs or missing AsNoTracking calls β problems that are EF Core misuse, not EF Core's design.
Add Dapper selectively for reporting, high-throughput read endpoints, or stored-procedure-heavy integrations where you already own the SQL. The hybrid approach is low-risk and well-supported.
Use Dapper exclusively only if you are building a read-side microservice, your team has strong SQL culture, and you have no intention of managing schema migrations from the application.
The answer for most enterprise .NET teams in 2026: EF Core for the domain, Dapper for the read paths that need it.
β Prefer a one-time tip? Buy us a coffee β every bit helps keep the content coming!
Frequently Asked Questions
Is Dapper faster than EF Core for all queries?
Not for all queries, and the gap is often smaller than benchmarks suggest. Dapper outperforms EF Core when using complex raw SQL with large result sets or extremely high request rates. For standard indexed CRUD operations, well-tuned EF Core with AsNoTracking performs within a few percent of Dapper. Profiling your specific workload is more useful than relying on generic benchmarks.
Can I use Dapper and EF Core in the same .NET project?
Yes. The hybrid approach is common and well-supported. You can obtain a DbConnection from your DbContext and pass it to Dapper's extension methods. EF Core handles writes, migrations, and domain operations; Dapper handles read-heavy or performance-critical paths. The two tools integrate cleanly within the same dependency injection setup.
Does EF Core support raw SQL queries?
Yes. EF Core supports raw SQL via FromSqlRaw, FromSqlInterpolated (SQL interpolation), and the ExecuteUpdate/ExecuteDelete bulk execution methods introduced in EF Core 7. You can drop to raw SQL for specific queries while keeping the rest of your data access in LINQ. This partially closes the SQL control gap with Dapper.
What are the biggest EF Core pitfalls teams hit in production?
The most common issues are: N+1 queries caused by lazy loading or missed Include statements, loading entire entity graphs when only a few columns are needed, missing AsNoTracking() on read-only queries, and over-reliance on automatic change tracking when doing bulk operations. Most of these are configuration or usage issues, not fundamental EF Core limitations. Enabling query logging in development catches the majority of them early.
Should I use Dapper or EF Core for a microservices architecture? It depends on the service's responsibility. Services that own their schema and perform domain operations benefit from EF Core's migrations and change tracking. Read-side services or API gateways that aggregate data across domains often benefit from Dapper's lighter footprint and direct SQL control. Many microservices teams standardise on EF Core by default and add Dapper selectively for read models and reporting services.
Does EF Core work well with stored procedures?
Yes, but with some friction. EF Core can execute stored procedures via FromSqlRaw or ExecuteStoredProcedure, and it can map results to entity types or keyless entities. However, EF Core's change tracking does not apply to stored procedure results, and multi-result-set procedures require more boilerplate. Dapper's QueryMultiple API handles stored procedures and multi-result-set mapping more naturally, which is why Dapper tends to be preferred in stored-procedure-heavy environments.
Is there a performance argument for Dapper in .NET 10? EF Core 10 has continued to improve query generation, compiled query caching, and bulk execution. The performance gap between Dapper and a properly tuned EF Core setup is narrower than ever. For most enterprise workloads on .NET 10, EF Core is fast enough. Dapper remains the better choice for specific scenarios requiring maximum throughput on read paths, but it is no longer the default answer whenever performance is mentioned.





