CloudBuilder/CloudBuilder.Core/DatabaseAccessor/UnitOfWork.cs
owenchen 1c0c83af5f ow
2026-05-12 10:09:31 +08:00

201 lines
5.9 KiB
C#

using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CloudBuilder.Core.DatabaseAccessor.Entity;
using Microsoft.Extensions.DependencyInjection;
namespace CloudBuilder.Core.DatabaseAccessor
{
public class UnitOfWork : IUnitOfWork
{
private readonly List<DbContext> _dbContexts = new List<DbContext>();
private DbTransaction _transaction;
private DbConnection _connection;
private DbContext _dbContext;
/// <summary>
/// 初始化一个<see cref="UnitOfWork"/>类型的新实例
/// </summary>
public UnitOfWork([FromKeyedServices(MasterDbContext.MASTER_DB_CONTEXT)] DbContext context)
{
_dbContext = context;
_dbContexts.Add(_dbContext);
_connection = _dbContext.Database.GetDbConnection();
}
/// <summary>
/// 获取 事务是否已提交
/// </summary>
public bool HasCommitted { get; private set; }
/// <summary>
/// 添加DbContext共享事务
/// </summary>
public void AddDbContext(DbContext dbContext)
{
_dbContexts.Add(dbContext);
}
public DbContext GetDbContext()
{
return _dbContext;
}
/// <summary>
/// 对数据库连接开启事务
/// </summary>
public virtual void BeginOrUseTransaction()
{
if (_dbContexts.Count == 0)
{
return;
}
if (_transaction?.Connection == null)
{
if (_connection.State != ConnectionState.Open)
{
_connection.Open();
}
_transaction = _connection.BeginTransaction();
}
foreach (DbContext context in _dbContexts)
{
if (context.Database.CurrentTransaction != null && context.Database.CurrentTransaction.GetDbTransaction() == _transaction)
{
continue;
}
//if (context.IsRelationalTransaction())
//{
//共享事务仅限关系数据库
context.Database.UseTransaction(_transaction);
//}
//else
//{
// context.Database.BeginTransaction();
//}
}
HasCommitted = false;
}
/// <summary>
/// 对数据库连接开启事务
/// </summary>
/// <param name="cancellationToken">异步取消标记</param>
/// <returns></returns>
public virtual async Task BeginOrUseTransactionAsync(CancellationToken cancellationToken = default)
{
if (_dbContexts.Count == 0)
{
return;
}
if (_transaction?.Connection == null)
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync(cancellationToken);
}
_transaction = _connection.BeginTransaction();
}
foreach (DbContext context in _dbContexts)
{
if (context.Database.CurrentTransaction != null && context.Database.CurrentTransaction.GetDbTransaction() == _transaction)
{
continue;
}
//if (context.IsRelationalTransaction())
//{
context.Database.UseTransaction(_transaction);
//}
//else
//{
// await context.Database.BeginTransactionAsync(cancellationToken);
//}
}
HasCommitted = false;
}
/// <summary>
/// 提交当前上下文的事务更改
/// </summary>
public virtual void Commit()
{
if (HasCommitted || _dbContexts.Count == 0 || _transaction == null)
{
return;
}
_transaction.Commit();
foreach (DbContext context in _dbContexts)
{
//if (context.IsRelationalTransaction())
//{
context.Database.CurrentTransaction.Dispose();
//关系型数据库共享事务
continue;
//}
//context.Database.CommitTransaction();
}
HasCommitted = true;
}
/// <summary>
/// 回滚所有事务
/// </summary>
public virtual void Rollback()
{
if (_transaction?.Connection != null)
{
_transaction.Rollback();
}
foreach (var context in _dbContexts)
{
//if (context.IsRelationalTransaction())
//{
CleanChanges(context);
if (context.Database.CurrentTransaction != null)
{
//context.Database.CurrentTransaction.Rollback();
context.Database.CurrentTransaction.Dispose();
}
continue;
//}
//context.Database.RollbackTransaction();
}
HasCommitted = true;
}
private static void CleanChanges(DbContext context)
{
var entries = context.ChangeTracker.Entries().ToArray();
foreach (var entry in entries)
{
entry.State = EntityState.Detached;
}
}
public void Dispose()
{
_transaction?.Dispose();
foreach (DbContext context in _dbContexts)
{
context.Dispose();
}
}
}
}