Dapper是一款轻量级的ORM框架,在实际开发中经常需要同时操作多个数据库或者多个数据资源,此时就需要分布式事务来保证操作的原子性。TransactionScope是.NET内置的分布式事务管理组件,可以和Dapper无缝配合实现分布式事务处理。

TransactionScope基础概念
TransactionScope位于System.Transactions命名空间下,它会自动创建和管理事务,开发者不需要手动编写事务开始、提交、回滚的代码。当在TransactionScope的作用域内执行数据库操作时,这些操作会自动加入当前事务,只有当所有操作都成功执行后,事务才会提交,任意一个操作失败都会导致整个事务回滚。
Dapper结合TransactionScope单数据库事务示例
首先需要在项目中安装Dapper包,然后引入相关命名空间:
using System.Data.SqlClient; using System.Transactions; using Dapper;
下面是单数据库下使用TransactionScope和Dapper执行事务操作的示例,假设我们有一个用户表和一个订单表,需要同时插入用户和订单数据:
class User
{
public int Id { get; set; }
public string UserName { get; set; }
}
class Order
{
public int Id { get; set; }
public int UserId { get; set; }
public string OrderNo { get; set; }
}
class Program
{
static string connStr = "Server=127.0.0.1;Database=TestDB;Uid=sa;Pwd=123456;";
static void Main()
{
// 创建TransactionScope实例,使用using确保作用域结束后自动释放
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
// 插入用户数据
string insertUserSql = "INSERT INTO User (UserName) VALUES (@UserName); SELECT CAST(SCOPE_IDENTITY() AS INT)";
int userId = conn.ExecuteScalar<int>(insertUserSql, new { UserName = "测试用户" });
// 插入订单数据,关联上面的用户ID
string insertOrderSql = "INSERT INTO Order (UserId, OrderNo) VALUES (@UserId, @OrderNo)";
conn.Execute(insertOrderSql, new { UserId = userId, OrderNo = "ORD20240501" });
}
// 所有操作执行完成,调用Complete方法提交事务
scope.Complete();
}
Console.WriteLine("事务提交成功");
}
}
如果上面的插入用户或者插入订单任意一个操作抛出异常,TransactionScope会自动回滚所有操作,数据库不会留下任何脏数据。
Dapper结合TransactionScope跨数据库分布式事务示例
当需要同时操作两个不同的数据库时,TransactionScope会自动升级为分布式事务,下面是操作两个不同数据库的示例:
static string connStr1 = "Server=127.0.0.1;Database=TestDB1;Uid=sa;Pwd=123456;";
static string connStr2 = "Server=127.0.0.1;Database=TestDB2;Uid=sa;Pwd=123456;";
static void CrossDbTransaction()
{
using (TransactionScope scope = new TransactionScope())
{
// 操作第一个数据库
using (SqlConnection conn1 = new SqlConnection(connStr1))
{
conn1.Open();
string sql1 = "INSERT INTO UserLog (LogContent) VALUES (@LogContent)";
conn1.Execute(sql1, new { LogContent = "用户注册日志" });
}
// 操作第二个数据库
using (SqlConnection conn2 = new SqlConnection(connStr2))
{
conn2.Open();
string sql2 = "INSERT INTO OrderLog (LogContent) VALUES (@LogContent)";
conn2.Execute(sql2, new { LogContent = "订单创建日志" });
}
scope.Complete();
}
Console.WriteLine("跨库分布式事务提交成功");
}
使用注意事项
- 需要确保数据库服务开启了分布式事务支持,比如SQL Server需要开启MSDTC服务,否则跨库事务会抛出异常。
- TransactionScope默认的事务隔离级别是Serializable,性能开销较大,如果不需要这么高的隔离级别,可以在创建TransactionScope时指定合适的隔离级别:
using (TransactionScope scope = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted })) { // 事务操作 } - 不要在TransactionScope作用域内执行耗时过长的操作,比如长时间的循环、网络请求等,否则容易导致事务超时,默认事务超时时间是1分钟,可以通过TransactionOptions设置超时时间。
- 如果使用的是MySQL数据库,需要确保连接字符串中添加
Enlist=true参数,否则操作不会自动加入TransactionScope的事务中。
常见问题解答
事务没有回滚是什么原因
检查是否在TransactionScope作用域内调用了scope.Complete()方法,如果调用了Complete但是操作失败,需要确认异常是否被捕获后没有抛出,只有未被处理的异常才会导致事务回滚。另外检查数据库连接是否支持分布式事务,连接字符串是否正确。
跨库事务抛出异常怎么排查
首先检查两个数据库是否都能正常连接,然后检查MSDTC服务是否正常运行,如果是不同服务器上的数据库,还需要确保服务器之间的防火墙开放了MSDTC对应的端口。可以在Windows事件查看器中查看分布式事务相关的错误日志,定位具体问题。
DapperTransactionScope分布式事务数据库事务修改时间:2026-06-29 10:12:25