轻量高效的ORM利器:Dapper在C#中的实践指南
Dapper是由Stack Overflow团队开发的轻量级ORM库,专注于高性能数据库操作。与传统ORM(如Entity Framework)相比,Dapper通过扩展IDbConnection接口提供极简API,在保持代码简洁的同时,性能接近原生ADO.NET。其核心优势在于零配置映射、执行速度快(比EF快2-10倍),特别适合高并发场景。
一、Dapper的核心特点
- 高性能
动态生成IL代码映射查询结果到对象,消除反射开销。 - 轻量级
仅15个核心方法(如Query, Execute),无复杂跟踪机制。 - 类型安全
强类型参数和返回值,支持泛型。 - 直接SQL控制
开发者完全掌控SQL语句,避免ORM自动生成低效查询。 - 多数据库支持
兼容SQL Server、MySQL、SQLite等(需配合对应ADO.NET驱动)。
二、Dapper的实现原理
1. 扩展方法模式
public static IEnumerable<T> Query<T>(
this IDbConnection cnn,
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true)
- 通过扩展IDbConnection添加新方法,无缝集成现有ADO.NET代码。
2. 动态代码生成
- 首次查询时生成IL代码实现属性映射,后续调用直接使用编译后的委托,避免反射性能损耗。
3. 参数化查询
自动将匿名对象转换为DbParameter,防止SQL注入:
var user = conn.Query<User>("SELECT * FROM Users WHERE Id = @Id", new { Id = 1 });
三、C#实战示例
环境准备
- 安装NuGet包:
Install-Package Dapper
Install-Package System.Data.SQLite // 以SQLite为例
步骤1:定义实体类
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public int UserId { get; set; }
public decimal Amount { get; set; }
}
步骤2:基础CRUD操作
using (var conn = new SQLiteConnection("Data Source=test.db"))
{
conn.Open();
// 插入数据(返回自增ID)
var newId = conn.ExecuteScalar<int>(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email); SELECT last_insert_rowid();",
new { Name = "Alice", Email = "alice@example.com" });
// 查询单条记录
var user = conn.QueryFirstOrDefault<User>(
"SELECT * FROM Users WHERE Id = @Id",
new { Id = newId });
// 更新操作
var rowsAffected = conn.Execute(
"UPDATE Users SET Email = @NewEmail WHERE Id = @Id",
new { NewEmail = "alice2@example.com", Id = newId });
// 查询列表
var users = conn.Query<User>("SELECT * FROM Users WHERE Name LIKE '%a%'");
}
步骤3:多表关联查询(一对多映射)
var sql = @"
SELECT u.*, o.*
FROM Users u
INNER JOIN Orders o ON u.Id = o.UserId
WHERE u.Id = @UserId";
var users = conn.Query<User, Order, User>(
sql,
(user, order) =>
{
user.Orders ??= new List<Order>();
user.Orders.Add(order);
return user;
},
new { UserId = 1 },
splitOn: "OrderId" // 分割列名
).Distinct().ToList();
// 实体类补充:
public class User
{
// ...原有属性
public List<Order> Orders { get; set; }
}
步骤4:事务处理
using (var trans = conn.BeginTransaction())
{
try
{
conn.Execute(
"INSERT INTO Orders (UserId, Amount) VALUES (@UserId, @Amount)",
new { UserId = 1, Amount = 99.99m },
trans);
conn.Execute(
"UPDATE Users SET LastOrderDate = @Date WHERE Id = @Id",
new { Date = DateTime.Now, Id = 1 },
trans);
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
}
步骤5:批量操作
var users = new List<User>
{
new User { Name = "Bob", Email = "bob@test.com" },
new User { Name = "Charlie", Email = "charlie@test.com" }
};
conn.Execute(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email)",
users); // 自动遍历集合执行
四、性能优化技巧
- 异步操作
使用QueryAsync避免线程阻塞:
var users = await conn.QueryAsync<User>("SELECT * FROM Users");
- 参数复用
预编译参数对象提升重复查询性能。 - 结果缓冲
大数据集时关闭缓冲(buffered: false)减少内存占用:
var unbufferedUsers = conn.Query<User>("SELECT * FROM Users", buffered: false);
结语
Dapper以极简设计+极致性能成为.NET高性能数据库访问的首选。虽然需要手动编写SQL,但其直观的API和灵活的映射机制,特别适合追求性能的开发者。
相关文章
- 好消息!Delphi 的VCL & FMX 图形用户界面库在python中免费使用
- OpenGL 数学库 (GLM)_opengl函数库有哪些
- C++ Easyx图形库安装与使用_cpp图形库
- c++(图形)几何库及工具_几何c++测评
- java基础都在这了,小主们拿去吧_java基础知识总结 超详细
- Hutool JSONUtil巧妙过滤null值:JSON转Map数据清洗的终极方案
- java迭代器iterator_java迭代器使用
- HikariCP为啥这么火?SpringBoot选它的原因?
- Arrays.asList 的隐藏陷阱?一份完整的避坑指南与正确用法分享
- 编程英文 - 删除/移除/清除 (delete/remove/clear)