Dapper is a lightweight Object-Relational Mapper (ORM) for the .NET ecosystem. Developed by the Stack Overflow engineering team, it provides a fluent, low-ceremony way to interact with databases while retaining full command over SQL statements. Its reputation for speed and simplicity has made it a popular choice among .NET developers.
Core Characteristics
- Lightweight footprint: Dapper adds negligible overhead, making it one of the fastest ORMs available.
- SQL-first philosophy: Rather than abstracting SQL behind query builders, Dapper encourages you to write raw, optimized queries.
- Dynamic mapping: Results can be mapped to strongly-typed objects or dynamic types without prior schema definition.
- Async-first: The library exposes async methods for non-blocking database operations.
- Minimal API surface: The API is deliberately small, reducing the learning curve and keeping code straightforward.
Getting Started
Install Dapper via NuGet:
dotnet add package Dapper
Basic Usage Examples
Consider a Person entity and a matching People table:
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
public string EmailAddress { get; set; }
}
The snippets below illustrate typical CRUD operations with Dapper.
Retrieving Data
using System.Data.SqlClient;
using Dapper;
var connectionString = "Server=.;Database=Demo;Trusted_Connection=true;";
using (var conn = new SqlConnection(connectionString))
{
// Single row
var person = conn.QueryFirstOrDefault<Person>(
"SELECT * FROM People WHERE Id = @Id", new { Id = 1 });
// Multiple rows with filtering
var people = conn.Query<Person>(
"SELECT * FROM People WHERE EmailAddress LIKE @Domain",
new { Domain = "%@example.com" });
// Dynamic result (no predefined class)
var dynamicResults = conn.Query(
"SELECT * FROM People WHERE FullName = @Name",
new { Name = "John Doe" }).ToList();
}
Inserting a Record
using (var conn = new SqlConnection(connectionString))
{
var newId = conn.ExecuteScalar<int>(
"INSERT INTO People (FullName, EmailAddress) VALUES (@FullName, @EmailAddress); " +
"SELECT CAST(SCOPE_IDENTITY() AS INT);",
new { FullName = "Alice Smith", EmailAddress = "alice@example.com" });
}
Updating Data
using (var conn = new SqlConnection(connectionString))
{
var affected = conn.Execute(
"UPDATE People SET FullName = @FullName WHERE Id = @Id",
new { FullName = "Bob Johnson", Id = 2 });
}
Deleting a Row
using (var conn = new SqlConnection(connectionString))
{
var deletedCount = conn.Execute(
"DELETE FROM People WHERE Id = @Id",
new { Id = 3 });
}
Why Chooce Dapper?
Dapper strikes a balance between the convenience of an ORM and the control of raw ADO.NET. It eliminates boilerplate code for mapping and connection management, yet doesn't hide the SQL. This makes it ideal for performance-sensitive applications or teams that prefer explicit, predictable database interactions. The examples above show how terse and expressive Dapper code can be for everyday database tasks.