当前位置:首页 > Web开发 > 正文

如果你有细细观察的话

2024-03-31 Web开发

标签:

1.事情单元(UnitOfWork)是什么?

  Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

  UnitOfWork是Martin Fowler提出的,,上面是他说的话,这里要注意的就是分两个时间点,a)业务操纵过程中,对操纵的CUD操纵的东西状态进行跟踪操纵; b) CUD操纵完毕提交到数据库,UnitOfWork保证业务提交使用同意上下文东西,从而保证了事务的一致性,假设提交掉败直接回滚。

  简单说:UnitOfWork可以说是一个开关,开:用于上下文的获取,供所有的仓储东西使用;关:提交操纵,提交的过程包罗事务控制(是否回滚)。

  所以他这一句话我们可以明确这几个对象:

  1. 一个东西用于存放 业务操纵的东西(我们结合仓储使用就是仓储了) repository的姑且存储东西;
  2. 同一业务操纵的上下文必需连结一致(同一上下文东西);
  3. 维护当前业务的变换操纵;
  4. 事务控制;

  依据这几点,我们就可以写出想要的代码,(姑且先刨除 第三点 ,后面会有增补),先声明:这里未考虑多上下文的情况,因为我这边用不到,但是实现也对照简单,可以将涉及到的hashtable东西换成dictionary等,键为上下位东西类型或者名称。

  接口界说:

/// <summary> /// 事情单元接口 /// </summary> public interface IUnitOfWork : IDisposable { IRepository<TEntity, TKey> Repository<TEntity, TKey>() where TEntity : class, IEntity<TKey>; void BeginTransaction(); int Commit(); Task<int> CommitAsync(); } public class UnitOfWork : IUnitOfWork { /// <summary> /// 处事供给器,主要用于查找 框架配置东西,以及DbContextOptionBuilder东西 /// </summary> private readonly IServiceProvider _provider; /// <summary> /// 当前请求涉及的scope生命的仓储东西 /// </summary> private Hashtable repositorys; private IDbContextTransaction _dbTransaction { get; set; } /// <summary> /// 上下文东西,UnitOfWork内部初始化上下文东西,供当前scope内的操纵使用,保证同一上下文 /// </summary> public DbContext DbContext => GetDbContext(); public UnitOfWork(IServiceProvider provider) { _provider = provider; } public IRepository<TEntity, TKey> Repository<TEntity, TKey>() where TEntity : class, IEntity<TKey> { if (repositorys == null) repositorys = new Hashtable(); var entityType = typeof(TEntity); if (!repositorys.ContainsKey(entityType.Name)) { var baseType = typeof(Repository<,>); var repositoryInstance = Activator.CreateInstance(baseType.MakeGenericType(entityType), DbContext); repositorys.Add(entityType.Name, repositoryInstance); } return (IRepository<TEntity, TKey>)repositorys[entityType.Name]; } public void BeginTransaction() { //DbContext.Database.UseTransaction(_dbTransaction);//如果多上下文,我们可是在其他上下文直接使用 UserTransaction使用已存在的事务 _dbTransaction = DbContext.Database.BeginTransaction(); } public int Commit() { int result = 0; try { result = DbContext.SaveChanges(); if (_dbTransaction != null) _dbTransaction.Commit(); } catch (Exception ex) { result = -1; CleanChanges(DbContext); _dbTransaction.Rollback(); throw new Exception($"Commit 异常:{ex.InnerException}/r{ ex.Message}"); } return result; } public async Task<int> CommitAsync() { int result = 0; try { result = await DbContext.SaveChangesAsync(); if (_dbTransaction != null) _dbTransaction.Commit(); } catch (Exception ex) { result = -1; CleanChanges(DbContext); _dbTransaction.Rollback(); throw new Exception($"Commit 异常:{ex.InnerException}/r{ ex.Message}"); } return await Task.FromResult(result); } private DbContext GetDbContext() { var options = _provider.ESoftorOption(); IDbContextOptionsBuilderCreator builderCreator = _provider.GetServices<IDbContextOptionsBuilderCreator>() .FirstOrDefault(d => d.DatabaseType == options.ESoftorDbOption.DatabaseType); if (builderCreator == null) throw new Exception($"无法解析数据库类型为:{options.ESoftorDbOption.DatabaseType}的{typeof(IDbContextOptionsBuilderCreator).Name}实例"); //DbContextOptionsBuilder var optionsBuilder = builderCreator.Create(options.ESoftorDbOption.ConnectString, null);//null可以换成缓存中获取connection东西,以便性能的提升 if (!(ActivatorUtilities.CreateInstance(_provider, options.ESoftorDbOption.DbContextType, optionsBuilder.Options) is DbContext)) throw new Exception($"上下文东西'{options.ESoftorDbOption.DbContextType.AssemblyQualifiedName}'实例化掉败,请确认配置文件已正确配置"); return dbContext; } /// <summary> /// 操纵掉败,还原跟踪状态 /// </summary> /// <param name="context"></param> private static void CleanChanges(DbContext context) { var entries = context.ChangeTracker.Entries().ToArray(); for (int i = 0; i < entries.Length; i++) { entries[i].State = EntityState.Detached; } } public void Dispose() { _dbTransaction.Dispose(); DbContext.Dispose(); GC.SuppressFinalize(this); } } 2.怎么用?

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30563.html