如何使用 dapper.net 的事务?

我想在多个表上运行多个 insert 语句。我正在使用 dapper.net。我没有看到任何处理 dapper.net 事务的方法。

请分享您对如何使用 dapper.net 进行事务处理的想法。

93744 次浏览

您应该能够使用 TransactionScope,因为 Dapper 只运行 ADO.NET 命令。

using (var scope = new TransactionScope())
{
// open connection
// insert
// insert
scope.Complete();
}

下面是代码片段:

using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}

请注意,您需要添加对 System.Transactions程序集的引用,因为默认情况下不引用它。

我更倾向于使用更直观的方法,直接从连接获取交易:

// This called method will get a connection, and open it if it's not yet open.
using (var connection = GetOpenConnection())
using (var transaction = connection.BeginTransaction())
{
connection.Execute(
"INSERT INTO data(Foo, Bar) values (@Foo, @Bar);", listOf5000Items, transaction);
transaction.Commit();
}

丹尼尔的回答对我有效。为了完整起见,下面的代码片段演示了使用事务作用域和 dapper 进行提交和回滚:

using System.Transactions;
// _sqlConnection has been opened elsewhere in preceeding code
using (var transactionScope = new TransactionScope())
{
try
{
long result = _sqlConnection.ExecuteScalar<long>(sqlString, new {Param1 = 1, Param2 = "string"});


transactionScope.Complete();
}
catch (Exception exception)
{
// Logger initialized elsewhere in code
_logger.Error(exception, $"Error encountered whilst executing  SQL: {sqlString}, Message: {exception.Message}")


// re-throw to let the caller know
throw;
}
} // This is where Dispose is called

考虑到您所有的表都在单个数据库中,我不同意在这里的一些答案中建议的 TransactionScope解决方案。请参阅 这个答案。

  1. TransactionScope通常用于分布式事务; 跨不同数据库的事务可能位于不同的系统上。这需要在操作系统和 SQLServer 上进行一些配置,没有这些配置就无法工作。如果所有查询都针对单个数据库实例,则不建议这样做。
    但是,对于单个数据库,当您需要将代码包含在不在您控制之下的事务中时,这可能非常有用。对于单个数据库,它也不需要特殊的配置。

  2. connection.BeginTransaction是 ADO.NET 语法,用于针对单个数据库实现事务(C # 、 VB.NET 等)。这不适用于多个数据库。

因此,connection.BeginTransaction()是更好的选择。

甚至更好的处理事务的方法是实现 UnitOfWork,就像 这个答案中解释的那样。

在 Dapper 中有3种处理事务的方法。

  1. 简单交易
  2. 事务范围中的事务
  3. 使用 Dapper 事务(额外的金属包装 最喜欢的方法)

您可以在官方的教程网站 给你上找到更多关于这些交易方法的信息

以下是交易方法的细分,以供参考

1. 简单交易

在本例中,您将在现有的 db 连接上创建一个事务,然后将该事务传递给 dapper 上的 Execute 方法(这是一个可选参数)。

完成所有工作后,只需提交事务即可。

string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";


using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
connection.Open();
    

using (var transaction = connection.BeginTransaction())
{
connection.Execute(sql, new {CustomerName = "Mark"}, transaction: transaction);
connection.Execute(sql, new {CustomerName = "Sam"}, transaction: transaction);
connection.Execute(sql, new {CustomerName = "John"}, transaction: transaction);
        

transaction.Commit();
}
}

2. 事务范围内的事务

如果希望创建事务作用域,则需要在创建数据库连接之前执行此操作。一旦创建了事务作用域,就可以简单地执行所有操作,然后执行一个调用来完成事务,然后提交所有命令

using (var transaction = new TransactionScope())
{
var sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";


using (var connection = My.ConnectionFactory())
{
connection.Open();


connection.Execute(sql, new {CustomerName = "Mark"});
connection.Execute(sql, new {CustomerName = "Sam"});
connection.Execute(sql, new {CustomerName = "John"});
}


transaction.Complete();
}

3. 使用 Dapper 交易

这是在代码中实现事务的最有利的方法,因为它使代码易于阅读和实现。SQL Transaction 的扩展实现称为 Dapper Transaction (可以找到 给你) ,它允许您直接运行 SQL 执行事务。

string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";


using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
connection.Open();
    

using (var transaction = connection.BeginTransaction())
{
transaction.Execute(sql, new {CustomerName = "Mark"});
transaction.Execute(sql, new {CustomerName = "Sam"});
transaction.Execute(sql, new {CustomerName = "John"});


transaction.Commit();
}
}