Wes*_*ley 3 .net c# oracle transactions dapper
我目前在一层中有两个类,它们执行将数据包含在数据库中的操作:
using Dapper;
using System;
using System.Data.SqlClient;
using System.Linq;
namespace repositories
{
public class DAOBook
{
private readonly string _connection;
public DAOBook(string databaseConnection)
{
_connection = databaseConnection;
}
public bool IncludeBook(string title)
{
try
{
using (var connection = new SqlConnection(_connection))
{
var sql = $@"
INSERT INTO books
(title)
VALUES
('{title}' ";
var result = connection.Execute(sql);
return result != 0;
}
}
catch (Exception ex)
{
throw new Exception($"{ex.Message}", ex);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
using Dapper;
using System;
using System.Data.SqlClient;
using System.Linq;
namespace repositories
{
public class DAOBookTag
{
private readonly string _connection;
public DAOBookTag(string databaseConnection)
{
_connection = databaseConnection;
}
public bool IncludeBookTag(string tag, int userid)
{
try
{
using (var connection = new SqlConnection(_connection))
{
var sql = $@"
INSERT INTO bookTag
(tag, userid)
VALUES
('{tag}', {userid} ";
var result = connection.Execute(sql);
return result != 0;
}
}
catch (Exception ex)
{
throw new Exception($"{ex.Message}", ex);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的服务层中,我可以正常调用这两个类,并将它们插入数据库中。
try
{
var connectionString = "<my_connection_string>";
var daoBook = new DAOBook(connectionString);
var daoBookTag = new DAOBookTag(connectionString);
dao.IncludeBook("Alice");
dao.IncludeBookTag("Romance", 1);
}
catch (Exception ex)
{
throw new Exception($"{ex.Message}", ex);
}
Run Code Online (Sandbox Code Playgroud)
但是,我想放置一个事务控制,以便在插入第二个类时出现错误时,它会撤消 catch 中的事务,如下所示:
try
{
var connectionString = "<my_connection_string>";
var daoBook = new DAOBook(connectionString);
var daoBookTag = new DAOBookTag(connectionString);
// begin transaction
dao.IncludeBook("Alice");
dao.IncludeBookTag("Romance", 1);
// commit
}
catch (Exception ex)
{
// rollback
throw new Exception($"{ex.Message}", ex);
}
Run Code Online (Sandbox Code Playgroud)
我知道这一定是初学者的问题,但我似乎无法找到让两个持久性类共享同一事务的方法。
我看到了实现 Dapper 事务控制的示例,但我不知道如何在我的服务层(而不是持久层)中实现它。 https://riptutorial.com/dapper/example/22536/using-a-transaction
谢谢
ADO.NET 中有两种处理事务的方法;通常首选的机制是 ADO.NET 事务,即BeginTransaction
. 这有局限性,但非常有效,并且可以本地映射到大多数提供商。ADO.NET 事务的关键限制是它只能跨越一个连接,并且连接的持续时间必须至少与事务一样长。
在Dapper使用方面,还必须将交易传递到调用中;例如:
using (var conn = new SqlConnection(connectionString))
{
connection.Open();
using (var tran = connection.BeginTransaction())
{
// ... your work
tran.Commit();
}
}
Run Code Online (Sandbox Code Playgroud)
其中“你的工作”在这里有效地使用相同的conn
和tran
实例,使用:
var result = conn.Execute(sql, args, transaction: tran);
Run Code Online (Sandbox Code Playgroud)
更懒惰的方法是使用TransactionScope
. 这使用起来更简单,但也更复杂。我通常建议不要这样做,但它确实有效。
您还应该参数化:
var sql = @"
INSERT INTO bookTag (tag, userid)
VALUES (@tag, @userId)";
var result = connection.Execute(sql, new { tag, userId });
Run Code Online (Sandbox Code Playgroud)