Dapper

server/2024/12/23 5:13:06/

Dapper 简介

Dapper 是一个轻量级的 ORM(对象关系映射)库,由 Stack Overflow 团队开发并维护。它旨在提供高效的数据库访问,同时保持代码的简洁性和性能。Dapper 的核心功能是将 SQL 查询结果自动映射到 C# 对象,而不需要编写大量的手动映射代码。

为什么选择 Dapper?
  1. 轻量级:Dapper 只是一个小型的库,不会像 Entity Framework 或 NHibernate 那样引入大量依赖或复杂的配置。
  2. 高性能:Dapper 的性能非常接近直接使用 ADO.NET,因为它只做了一层简单的封装,没有额外的开销。
  3. 灵活性:Dapper 允许你编写原始 SQL 查询,提供了对数据库的完全控制,同时也支持参数化查询和多结果集处理。
  4. 简单易用:Dapper 的 API 非常简单,学习曲线低,适合快速开发和原型设计。

安装 Dapper

你可以通过 NuGet 包管理器安装 Dapper。在 Visual Studio 中,打开包管理器控制台并运行以下命令:

dotnet add package Dapper

或者,在项目文件中添加以下依赖项:

<PackageReference Include="Dapper" Version="2.0.123" />

基本用法

1. 查询单个对象

假设你有一个 User 类,并且你想从数据库中查询单个用户:

public class User
{public int Id { get; set; }public string Name { get; set; }public string Email { get; set; }
}using (var connection = new SqliteConnection(_connectionString))
{var user = await connection.QueryFirstOrDefaultAsync<User>("SELECT * FROM Users WHERE Id = @Id", new { Id = 1 });Console.WriteLine($"User: {user.Name}, Email: {user.Email}");
}
  • QueryFirstOrDefaultAsync<T>:执行查询并返回第一个匹配的结果,如果没有任何结果则返回默认值(null 或 default(T))。
  • @Id:参数化查询,防止 SQL 注入攻击。
2. 查询多个对象

如果你想查询多个用户,可以使用 QueryAsync<T>

using (var connection = new SqliteConnection(_connectionString))
{var users = await connection.QueryAsync<User>("SELECT * FROM Users");foreach (var user in users){Console.WriteLine($"User: {user.Name}, Email: {user.Email}");}
}
  • QueryAsync<T>:执行查询并返回一个 IEnumerable<T>,表示查询结果的集合。
3. 插入数据

Dapper 也支持插入、更新和删除操作。你可以使用 ExecuteAsync 方法来执行这些操作:

using (var connection = new SqliteConnection(_connectionString))
{var newUser = new User { Name = "John Doe", Email = "john.doe@example.com" };var rowsAffected = await connection.ExecuteAsync("INSERT INTO Users (Name, Email) VALUES (@Name, @Email)", newUser);Console.WriteLine($"Rows affected: {rowsAffected}");
}
  • ExecuteAsync:执行非查询语句(如 INSERTUPDATEDELETE),并返回受影响的行数。
4. 更新数据

更新操作与插入类似,只需提供要更新的条件:

using (var connection = new SqliteConnection(_connectionString))
{var updatedUser = new { Id = 1, Name = "Jane Doe", Email = "jane.doe@example.com" };var rowsAffected = await connection.ExecuteAsync("UPDATE Users SET Name = @Name, Email = @Email WHERE Id = @Id", updatedUser);Console.WriteLine($"Rows affected: {rowsAffected}");
}
5. 删除数据

删除操作也非常简单:

using (var connection = new SqliteConnection(_connectionString))
{var rowsAffected = await connection.ExecuteAsync("DELETE FROM Users WHERE Id = @Id", new { Id = 1 });Console.WriteLine($"Rows affected: {rowsAffected}");
}
6. 多结果集处理

Dapper 支持多结果集查询,即一次查询返回多个表的数据。你可以使用 QueryMultiple 方法来处理这种情况:

using (var connection = new SqliteConnection(_connectionString))
{using (var multi = await connection.QueryMultipleAsync("SELECT * FROM Users; SELECT * FROM Orders")){var users = await multi.ReadAsync<User>();var orders = await multi.ReadAsync<Order>();foreach (var user in users){Console.WriteLine($"User: {user.Name}");}foreach (var order in orders){Console.WriteLine($"Order: {order.OrderId}");}}
}
  • QueryMultipleAsync:执行多结果集查询,并返回一个 SqlMapper.GridReader 对象,可以通过 ReadAsync<T> 方法逐个读取每个结果集。

高级功能

1. 自动映射复杂对象

Dapper 支持自动映射复杂对象,包括嵌套对象和多个表的联合查询。例如,假设你有 UserOrder 两个表,并且你想查询每个用户的订单信息:

public class UserWithOrders
{public int Id { get; set; }public string Name { get; set; }public List<Order> Orders { get; set; }
}public class Order
{public int OrderId { get; set; }public DateTime OrderDate { get; set; }
}using (var connection = new SqliteConnection(_connectionString))
{var sql = @"SELECT u.Id, u.Name, o.OrderId, o.OrderDateFROM Users uLEFT JOIN Orders o ON u.Id = o.UserId";var result = await connection.QueryAsync<User, Order, UserWithOrders>(sql,(user, order) =>{var userWithOrders = new UserWithOrders{Id = user.Id,Name = user.Name,Orders = new List<Order>()};if (order != null){userWithOrders.Orders.Add(order);}return userWithOrders;},splitOn: "OrderId");// 使用 LINQ 进行分组var usersWithOrders = result.GroupBy(x => x.Id).Select(g => new UserWithOrders{Id = g.Key,Name = g.First().Name,Orders = g.SelectMany(x => x.Orders).ToList()}).ToList();foreach (var user in usersWithOrders){Console.WriteLine($"User: {user.Name}");foreach (var order in user.Orders){Console.WriteLine($"  Order: {order.OrderId}, Date: {order.OrderDate}");}}
}
  • QueryAsync<T1, T2, TReturn>:用于映射多个表的联合查询。splitOn 参数指定了如何区分不同的表(通常是主键列)。
  • GroupBy:用于将多个结果集分组为单个对象。
2. 事务支持

Dapper 也支持事务操作。你可以使用 BeginTransaction 方法来启动一个事务,并在提交或回滚时进行控制:

using (var connection = new SqliteConnection(_connectionString))
{using (var transaction = await connection.BeginTransactionAsync()){try{// 执行插入操作await connection.ExecuteAsync("INSERT INTO Users (Name, Email) VALUES (@Name, @Email)", new { Name = "John Doe", Email = "john.doe@example.com" }, transaction);// 执行另一个插入操作await connection.ExecuteAsync("INSERT INTO Orders (UserId, OrderDate) VALUES (@UserId, @OrderDate)", new { UserId = 1, OrderDate = DateTime.Now }, transaction);// 提交事务await transaction.CommitAsync();}catch (Exception ex){// 回滚事务await transaction.RollbackAsync();throw;}}
}

性能优化

Dapper 的性能非常接近原生 ADO.NET,因为它只做了一层简单的封装。为了进一步提高性能,你可以考虑以下几点:

  1. 使用缓存Dapper 提供了内置的查询计划缓存机制,可以在多次执行相同的查询时提高性能。
  2. 批量操作对于批量插入或更新操作,可以使用 ExecuteBatch 或 BulkCopy 等方法来减少数据库往返次数。
  3. 异步编程尽量使用异步方法(如 QueryAsyncExecuteAsync)来避免阻塞主线程,特别是在 Web 应用程序中。

总结

Dapper 是一个非常强大且灵活的轻量级 ORM 库,适合需要高效数据库访问的应用程序。它提供了简单易用的 API,支持多种数据库类型(如 SQLite、SQL Server、MySQL 等),并且能够很好地与现有的 ADO.NET 代码集成。如果你希望在保持高性能的同时简化数据库操作,Dapper 是一个非常好的选择。


http://www.ppmy.cn/server/152410.html

相关文章

Java web的发展历史

目录 前言&#xff1a; 一.Model I和Model II 1.Model I开发模式 ​编辑 2.Model II开发模式 二. MVC模式 前言&#xff1a; 该篇文章主要介绍了Java web的发展历史&#xff0c;以及MVC相关内容 一.Model I和Model II 1.Model I开发模式 Model1的开发模式是&#xff…

uniapp自定义树型结构数据弹窗,给默认选中的节点,禁用所有子节点

兼容H5、安卓App、微信小程序 实现逻辑&#xff1a;给默认选中节点的所有子节点添加一个disabled属性&#xff0c;以此禁用子节点。 /components/sonTreeNode/sonTreeNode.vue 封装成组件 <template><view><view :class"[item,item.is_level1?pL1:item…

Linux docker-20.10.9安装

Linux Docker20.10.9安装 解压文件 tar -xvf docker-20.10.9.tgz 给docker执行文件赋予可执行权限 chmod 755 -R docker/复制docker到/usr/bin/目录下,使docker命令可以执行 cp docker/* /usr/bin/将Docker注册为service&#xff0c;创建docker.service文件 vim /etc/syst…

SQL注入的那些面试题总结

一、知识储备类 1.SQL与NoSQL的区别&#xff1f; SQL&#xff1a;关系型数据库 NoSQL&#xff1a;非关系型数据库 存储方式&#xff1a;SQL具有特定的结构表&#xff0c;NoSQL存储方式灵活 性能&#xff1a;NoSQL较优于SQL 数据类型&#xff1a;SQL适用结构化数据&#xff0c;…

在 Spark 上实现 Graph Embedding

在 Spark 上实现 Graph Embedding 主要涉及利用大规模图数据来训练模型&#xff0c;以学习节点的低维表示&#xff08;嵌入&#xff09;。这些嵌入能够捕捉和反映图中的节点间关系&#xff0c;如社交网络的朋友关系或者物品之间的相似性。在 Spark 上进行这一任务&#xff0c;可…

在 Spring Boot 3 中实现基于角色的访问控制

基于角色的访问控制 (RBAC) 是一种有价值的访问控制模型,可增强安全性、简化访问管理并提高效率。它在管理资源访问对安全和运营至关重要的复杂环境中尤其有益。 我们将做什么 我们有一个包含公共路由和受限路由的 Web API。受限路由需要数据库中用户的有效 JWT。 现在用户…

智慧商城:点击“加入购物车”判断是否登录来进行跳转到登录页登录并回跳 + 发请求渲染加入购物车数量的角标

点击“加入购物车”判断是否登录来进行跳转到登录页登录并回跳 按需引入需要的 Dialog 组件并进行全局注册 Vue.use( )仅仅在Vue组件的上下文中起作用&#xff0c;所以在Vue组件中通过 this.$ 来使用 在 js 文件中则还要导入&#xff0c;然后直接使用&#xff0c;并不需要 this…

【ETCD】【Linearizable Read OR Serializable Read】ETCD 数据读取:强一致性 vs 高性能,选择最适合的读取模式

ETCD 提供了两种不同类型的读取操作方式&#xff0c;分别是 Linearizable Read&#xff08;线性化读取&#xff09;和 Serializable Read&#xff08;可串行化读取&#xff09;。这两种方式主要区分在读取数据时对一致性的要求不同。 目录 1. Linearizable Read&#xff08;线…