- Notifications
You must be signed in to change notification settings - Fork 893
工作单元
2881099 edited this page Dec 7, 2023 · 32 revisions
中文 | English
UnitOfWork 可将多个仓储放在一个单元管理执行,最终通用 Commit 执行所有操作,内部使用了数据库事务;
static IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, connectionString) .UseAutoSyncStructure(true) //自动同步实体结构到数据库 .Build(); //请务必定义成 Singleton 单例模式using (var uow = fsql.CreateUnitOfWork()) { var songRepo = fsql.GetRepository<Song>(); var userRepo = fsql.GetRepository<User>(); songRepo.UnitOfWork = uow; //手工绑定工作单元 userRepo.UnitOfWork = uow; songRepo.Insert(new Song()); userRepo.Update(...); uow.Orm.Insert(new Song()).ExecuteAffrows(); //注意:uow.Orm 和 fsql 都是 IFreeSql //uow.Orm CRUD 与 uow 是一个事务(理解为临时 IFreeSql) //fsql CRUD 与 uow 不在一个事务 uow.Commit(); }参考:在 asp.net core 中使用 TransactionalAttribute + UnitOfWorkManager 实现多种事务传播
uow.GetOrBeginTransaction() 方法可获取事务对象。
public interface IUnitOfWork : IDisposable { /// <summary> /// 该对象 Select/Delete/Insert/Update/InsertOrUpdate 与工作单元事务保持一致,可省略传递 WithTransaction /// </summary> IFreeSql Orm { get; } DbTransaction GetOrBeginTransaction(bool isCreate = true); IsolationLevel? IsolationLevel { get; set; } void Commit(); void Rollback(); /// <summary> /// 工作单元内的实体变化跟踪 /// </summary> DbContext.EntityChangeReport EntityChangeReport { get; } /// <summary> /// 用户自定义的状态数据,便于扩展 /// </summary> Dictionary<string, object> States { get; } }全局设置:
fsql.SetDbContextOptions(opt => { opt.OnEntityChange = report => { Console.WriteLine(report); }; });单独设置:
var uow = fsql.CreateUnitOfWork(); uow.OnEntityChange = report => { Console.WriteLine(report); };参数 report 是一个 List 集合,集合元素的类型定义如下:
public class ChangeInfo { public object Object { get; set; } public EntityChangeType Type { get; set; } /// <summary> /// Type = Update 的时候,获取更新之前的对象 /// </summary> public object BeforeObject { get; set; } } public enum EntityChangeType { Insert, Update, Delete, SqlRaw }| 变化类型 | 说明 |
|---|---|
| Insert | 实体对象被插入 |
| Update | 实体对象被更新 |
| Delete | 实体对象被删除 |
| SqlRaw | 执行了SQL语句 |
SqlRaw 目前有两处地方比较特殊:
- 多对多联级更新导航属性的时候,对中间表的全部删除操作;
- 通用仓储类 BaseRepository 有一个 Delete 方法,参数为表达式,而并非实体;
int Delete(Expression<Func<TEntity, bool>> predicate);DbContext.SaveChanges,或者 Repository 对实体的 Insert/Update/Delete,或者 UnitOfWork.Commit 操作都会最多触发一次该事件。