Roadmap › Dapper — The Micro-ORM from Basics to Advanced › Module: Dapper Basics
Lessons in this course (8)
1. Setup and the core methods
Basic★ Must knowLesson 1 of 8
csharp
// dotnet add package Dapper
// dotnet add package Microsoft.Data.SqlClient
using Dapper;
using Microsoft.Data.SqlClient;
public record Product(int Id, string Name, string Category, decimal Price);
await using var conn = new SqlConnection(connectionString);
// Many rows
IEnumerable<Product> all = await conn.QueryAsync<Product>("SELECT Id, Name, Category, Price FROM dbo.Products");
// Exactly one row expected
Product p = await conn.QuerySingleAsync<Product>("SELECT * FROM dbo.Products WHERE Id = @Id", new { Id = 5 });
// First or nothing
Product? maybe = await conn.QueryFirstOrDefaultAsync<Product>(
"SELECT TOP 1 * FROM dbo.Products WHERE Category = @Cat ORDER BY Price", new { Cat = "Pens" });
// Scalar value
int count = await conn.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM dbo.Products");
// INSERT/UPDATE/DELETE — returns affected rows
int rows = await conn.ExecuteAsync("UPDATE dbo.Products SET Price = Price * 1.1 WHERE Category = @Cat", new { Cat = "Pens" });
// Insert and get the new id
int newId = await conn.QuerySingleAsync<int>(
"INSERT INTO dbo.Products (Name, Category, Price) OUTPUT INSERTED.Id VALUES (@Name, @Category, @Price)",
new { Name = "Gel pen", Category = "Pens", Price = 25m });| Method | Rows expected | Throws when |
|---|---|---|
Query<T> | 0..n | — |
QueryFirst<T> | ≥ 1 (takes first) | 0 rows |
QueryFirstOrDefault<T> | 0..n (takes first) | — |
QuerySingle<T> | exactly 1 | 0 or > 1 rows |
QuerySingleOrDefault<T> | 0 or 1 | > 1 rows |
Execute | — (returns affected count) | — |
ExecuteScalar<T> | first column of first row | — |
Mapping rules: column names match property names case-insensitively; use SQL aliases when names differ (SELECT ProductName AS Name); records/classes with constructors are matched by parameter names; set DefaultTypeMap.MatchNamesWithUnderscores = true to map product_name → ProductName.