Why Dapper
Dapper is a small library that keeps your SQL but writes the ADO.NET code around it for you - opening the connection, adding parameters, and turning rows into objects.
Journeyman · C# · T-SQL · Updated
After this lesson you can
- Explain what Dapper does for you, and what stays the same as ADO.NET
Key takeaways
- Dapper keeps your SQL and writes the ADO.NET code around it: it opens the connection, adds the parameters and turns each row into an object.
- Dapper builds each object by matching a column name to a property name.
dotnet add package Dapperadds the library, andusing Dapper;adds methods such asQueryto everySqlConnection.- Dapper is a micro-ORM: it maps rows to objects and stops there. Unlike Entity Framework Core, it leaves the SQL to you.
In Connecting Apps to SQL Server, every DAO method followed the same pattern: open a connection, create a command, add each parameter, run it, read each row, and copy each column into a property. The SQL was the interesting part; the rest was the same in every method.
Dapper is a small library that writes that repeated part for you. You still write the SQL. Dapper runs it, and turns the rows into your objects.
The same method, twice
Here's GetById from the ADO.NET Product DAO:
public Product? GetById(int productId)
{
string sql = """
SELECT ProductId, ProductName, CategoryId, UnitPrice, UnitsInStock
FROM Products
WHERE ProductId = @ProductId;
""";
using SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
using SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@ProductId", productId);
using SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
return new Product
{
ProductId = (int)reader["ProductId"],
ProductName = (string)reader["ProductName"],
CategoryId = reader["CategoryId"] as int?,
UnitPrice = reader["UnitPrice"] as decimal?,
UnitsInStock = reader["UnitsInStock"] as short?
};
}
return null;
}
And here it is with Dapper:
public Product? GetById(int productId)
{
string sql = """
SELECT ProductId, ProductName, CategoryId, UnitPrice, UnitsInStock
FROM Products
WHERE ProductId = @ProductId;
""";
using SqlConnection connection = new SqlConnection(connectionString);
return connection.QuerySingleOrDefault<Product>(sql, new { ProductId = productId });
}
The SQL is identical. What's gone is the plumbing: Dapper opens the connection, adds @ProductId from the object you pass, runs the query, and builds the Product by matching each column name to a property name.
A whole program
Add the package to a project that already has SqlClient:
dotnet add package Dapper
Then:
using Dapper;
using Microsoft.Data.SqlClient;
string connectionString = "Server=localhost;Database=Northwind;Integrated Security=true;TrustServerCertificate=true;";
using SqlConnection connection = new SqlConnection(connectionString);
List<Product> products = connection.Query<Product>(
"SELECT TOP (3) ProductId, ProductName, UnitPrice FROM Products ORDER BY UnitPrice DESC;").ToList();
foreach (Product product in products)
{
Console.WriteLine( quot;{product.ProductId}: {product.ProductName}, {product.UnitPrice:0.00}");
}
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; } = "";
public int? CategoryId { get; set; }
public decimal? UnitPrice { get; set; }
public short? UnitsInStock { get; set; }
}
38: Côte de Blaye, 263.50
29: Thüringer Rostbratwurst, 123.79
9: Mishi Kobe Niku, 97.00
using Dapper; adds new methods, such as Query, to every SqlConnection. (They're extension methods: methods a library adds to a class it didn't write.)
What Dapper is, and isn't
| Stays the same as ADO.NET | Dapper does for you |
|---|---|
| You write the SQL | Opens and closes the connection |
You use SqlConnection and your connection string |
Adds the parameters, from an object |
| You choose the queries, joins and indexes | Runs the command |
| SQL injection is avoided with parameters | Turns each row into an object, by column name |
Dapper is a micro-ORM: it maps rows to objects and stops there. Big ORMs, such as Entity Framework Core (which you'll meet in HTTP and Web APIs), also write the SQL for you. Dapper's choice is to keep the SQL in your hands, so what runs is the SQL you wrote, apart from expanding IN lists. It's fast, small, and widely used in .NET; this site's own services use it.
Check yourself
1 question to try on the lesson page.
So what
Same SQL, a tenth of the code. Dapper removes the repetitive part of data access, so each DAO method is the query, and a line to run it.
Key terms
- Dapper
- Micro-ORM
- ORM