在此处下载文章代码:
代码示例链接已删除,但解决方案仍保留在这里,以防其他人需要使用它。
我正在使用带有 ADO.NET 和 Dapper 的 DataLibrary 迁移到 .net 核心 Web 项目。我在 .NET 框架中有工作副本,但我已经提取了原始 DataLibrary 的具体细节,我正在努力让 .net 核心项目版本运行起来。
在使用新的依赖注入系统将事务功能集成到库中时,我遇到了困难。我的 DataLibrary 适用于基本的 CRUD 操作,但我还没有解开如何将事务逻辑应用到新库中的谜团。
我不打算使用实体框架等任何其他数据库技术,我只需要在正确的方向上推动如何调整我的示例代码项目类。我在那里发现的样本都没有帮助。
提前感谢社区可以提供的任何积极支持。
我尝试将 IDBTransaction 对象集成到我的示例中的代码中,并在第一次调用 Save 方法时对其进行初始化,该方法传入 bool 标志,表明该操作是应创建新连接还是使用类库连接/事务对象进行调用。如果使用事务来创建数据,开发人员将使用 DBLibrary 的 .Rollback() 或 .Commit() 方法来提交或回滚数据库调用。
程序在 var app = builder.Build(); 上不断失败;在 Web 项目的 Program.cs 文件中,因为它不知道如何在启用事务的版本中处理这些 IDBConnection 和 IDBTransaction 对象。
我找到了将 IDBTransaction 作为可空参数传递给每个方法调用的解决方案。如果事务 != null,则使用其上的连接来运行查询。我只需要创建两个版本的方法来调用 SaveData() 和 LoadData()。
public class SQLDB : IDataAccess
{
private readonly IConfiguration _config;
public SQLDB(IConfiguration config)
{
_config = config;
}
public async Task<List<T>> LoadData<T, U>(string queryStoredProc, U parameters, CommandType commandTypeName, string connectionStringName)
{
string? connectionString = _config.GetConnectionString(connectionStringName);
IDbConnection c = new SqlConnection(connectionString);
var rows = await c.QueryAsync<T>(queryStoredProc, parameters, commandType: commandTypeName);
return rows.ToList();
}
public async Task<List<T>> LoadData<T, U>(string queryStoredProc, U parameters, CommandType commandTypeName, IDbTransaction transaction)
{
var rows = await transaction.Connection
.QueryAsync<T>(queryStoredProc, parameters, commandType: commandTypeName, transaction: transaction);
return rows.ToList();
}
public async Task<int> SaveData<U>(string queryStoredProc, U parameters, CommandType commandTypeName, string connectionStringName)
{
string? connectionString = _config.GetConnectionString(connectionStringName);
IDbConnection c = new SqlConnection(connectionString);
return await c.ExecuteAsync(queryStoredProc, parameters, commandType: commandTypeName);
}
public async Task<int> SaveData<U>(string queryStoredProc, U parameters, CommandType commandTypeName, IDbTransaction transaction)
{
return await transaction.Connection
.ExecuteAsync(queryStoredProc, parameters, commandType: commandTypeName, transaction: transaction);
}
}
现在每个引用它的数据库调用都只是根据它传递正确的值,我们是否正在运行一个事务。
public class SystemUserData : ISystemUserData
{
private readonly IDataAccess _dataAccess;
private readonly ConnectionStringData _connectionStringData;
public SystemUserData(IDataAccess dataAccess, ConnectionStringData connectionStringData)
{
_dataAccess = dataAccess;
_connectionStringData = connectionStringData;
}
public async Task<List<SystemUserModel>> Get(int? UID, IDbTransaction? transaction)
{
string where = UID.HasValue ? $"WHERE UID = {UID}" : "";
if (transaction == null)
{
return await _dataAccess.LoadData<SystemUserModel, dynamic>
($"SELECT * FROM SystemUser {where};", new { },
CommandType.Text, _connectionStringData.SQLConnectionName);
}
else
{
return await _dataAccess.LoadData<SystemUserModel, dynamic>
($"SELECT * FROM SystemUser {where};", new { },
CommandType.Text, transaction);
}
}
public async Task<int> Save(SystemUserModel model, IDbTransaction? transaction)
{
string scrubbed_name = model.Name.Replace("'", "''");
string query = "INSERT INTO SystemUser (Name) VALUES ('@Name'); SELECT SCOPE_IDENTITY();";
query = query.Replace("@Name", scrubbed_name);
if (transaction == null)
{
return await _dataAccess.SaveData(query, new { }, CommandType.Text, _connectionStringData.SQLConnectionName);
}
else
{
return await _dataAccess.SaveData(query, new { }, CommandType.Text, transaction);
}
}