Roadmap › 1. .NET › Step 16
Dp

Dapper — The Micro-ORM from Basics to Advanced

What Dapper is and how it works inside, Query/QueryFirst/QuerySingle/Execute, parameters and SQL injection safety, stored procedures and output parameters, multi-mapping joins, QueryMultiple, transactions, bulk inserts and table-valued parameters, async and buffering, custom type handlers, DynamicParameters, repository and unit-of-work patterns, Dapper vs EF Core vs ADO.NET, performance and testing.
What it is & where it is used

Dapper is a lightweight object mapper ("micro-ORM") created by Stack Overflow (Sam Saffron and Marc Gravell, 2011). It adds extension methods to IDbConnection that run your SQL and map the results to objects — nearly as fast as hand-written ADO.NET, with a fraction of the code.

ADO.NETDapperEF Core
You write SQLYesYesNo (LINQ → SQL), optional raw SQL
Mapping rows to objectsManual (reader["Name"])Automatic by column nameAutomatic
Change tracking, migrations, relationshipsNoNoYes
PerformanceFastest (manual)~Same as ADO.NETGood, more overhead
Code volumeHighLowLowest for CRUD
Best forSpecial cases, bulkReports, read-heavy APIs, stored procedures, performance-critical pathsDomain models, CRUD, complex writes

Many teams combine them: EF Core for writes, Dapper for complex reads/reports (CQRS-lite).

Versions & history
YearMilestone
2011Dapper open-sourced by Stack Overflow
2012–2016Multi-mapping, QueryMultiple, async methods, .NET Core support
2017Dapper 1.50+ for .NET Standard
2019Dapper 2.0 — modern target frameworks
2023Dapper 2.1 — AOT-friendlier work begins; Dapper.AOT (source-generated, no runtime reflection emit)
2024–2025Dapper 2.1.x maintained; works with Microsoft.Data.SqlClient, Npgsql, MySqlConnector, SQLite

Related packages: Dapper.Contrib / Dapper.SimpleCRUD (generated CRUD), Dapper.AOT, DapperQueryBuilder, Dapper.Bulk.

Lifecycle

What happens when you call connection.Query<Order>(sql, new { CustomerId = 42 }):

  1. Dapper builds a cache key from the SQL text, the parameter object's type and the result type.
  2. First time only: it generates (via IL emit / compiled code) a parameter writer that turns the anonymous object's properties into DbParameters, and a row mapper that reads a DbDataReader row into an Order by matching column names to properties/constructor parameters. These are cached — later calls are fast.
  3. Opens the connection if it is closed (and closes it again afterwards).
  4. Creates a DbCommand, adds parameters, executes ExecuteReader.
  5. Maps each row with the cached mapper; with buffered: true (default) it reads all rows into a List<T> before returning.
  6. Disposes the reader and command.
Tools used to develop
  • NuGet: Dapper, Microsoft.Data.SqlClient (SQL Server), Npgsql, MySqlConnector, Microsoft.Data.Sqlite.
  • SQL Server Management Studio / Azure Data Studio for writing and tuning SQL; actual execution plans.
  • MiniProfiler (also from Stack Overflow) to see SQL timings per request.
  • Testcontainers (real SQL Server in Docker) for integration tests.