UnitOfWork

UnitOfWork 可将多个仓储放在一个单元管理执行,最终通用 Commit 执行所有操作,内部采用了数据库事务;

  1. var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" +
  2. "Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10";
  3. static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
  4. .UseConnectionString(FreeSql.DataType.MySql, connstr)
  5. .UseAutoSyncStructure(true) //自动同步实体结构到数据库
  6. .Build(); //请务必定义成 Singleton 单例模式

如何使用

  1. using (var uow = fsql.CreateUnitOfWork()) {
  2. var songRepo = fsql.GetRepository<Song>();
  3. songRepo.UnitOfWork = uow;
  4. var userRepo = fsql.GetRepository<User>();
  5. userRepo.UnitOfWork = uow;
  6. songRepo.Insert(new Song());
  7. userRepo.Update(...);
  8. uow.Commit();
  9. }

参考:在 asp.net core 中使用 TransactionalAttribute + UnitOfWorkManager 实现多种事务传播

接口定义

uow.GetOrBeginTransaction() 方法可获取事务对象。

  1. public interface IUnitOfWork : IDisposable {
  2. DbTransaction GetOrBeginTransaction(bool isCreate = true);
  3. IsolationLevel? IsolationLevel { get; set; }
  4. /// <summary>
  5. /// 是否启用工作单元
  6. /// </summary>
  7. bool Enable { get; }
  8. void Commit();
  9. void Rollback();
  10. /// <summary>
  11. /// 禁用工作单元
  12. /// <exception cref="Exception"></exception>
  13. /// <para></para>
  14. /// 若已开启事务(已有Insert/Update/Delete操作),调用此方法将发生异常,建议在执行逻辑前调用
  15. /// </summary>
  16. void Close();
  17. /// <summary>
  18. /// 开启工作单元
  19. /// </summary>
  20. void Open();
  21. /// <summary>
  22. /// 此工作单元内的实体变化跟踪
  23. /// </summary>
  24. DbContext.EntityChangeReport EntityChangeReport { get; }
  25. }

实体变化事件

全局设置:

  1. fsql.SetDbContextOptions(opt => {
  2. opt.OnEntityChange = report => {
  3. Console.WriteLine(report);
  4. };
  5. });

单独设置:

  1. var uow = fsql.CreateUnitOfWork();
  2. uow.OnEntityChange = report => {
  3. Console.WriteLine(report);
  4. };

参数 report 是一个 List 集合,集合元素的类型定义如下:

  1. public class ChangeInfo {
  2. public object Object { get; set; }
  3. public EntityChangeType Type { get; set; }
  4. /// <summary>
  5. /// Type = Update 的时候,获取更新之前的对象
  6. /// </summary>
  7. public object BeforeObject { get; set; }
  8. }
  9. public enum EntityChangeType { Insert, Update, Delete, SqlRaw }
变化类型 说明
Insert 实体对象被插入
Update 实体对象被更新
Delete 实体对象被删除
SqlRaw 执行了SQL语句

SqlRaw 目前有两处地方比较特殊:

  • 多对多联级更新导航属性的时候,对中间表的全部删除操作;
  • 通用仓储类 BaseRepository 有一个 Delete 方法,参数为表达式,而并非实体;
    1. int Delete(Expression<Func<TEntity, bool>> predicate);

DbContext.SaveChanges,或者 Repository 对实体的 Insert/Update/Delete,或者 UnitOfWork.Commit 操作都会最多触发一次该事件。