mirror of
https://github.com/dotnetcore/FreeSql.git
synced 2026-02-03 15:00:53 +08:00
Created Unit of Work (markdown)
127
Unit-of-Work.md
Normal file
127
Unit-of-Work.md
Normal file
@@ -0,0 +1,127 @@
|
||||
[中文](%e5%b7%a5%e4%bd%9c%e5%8d%95%e5%85%83) | **English**
|
||||
|
||||
UnitOfWork 可将多个仓储放在一个单元管理执行,最终通用 Commit 执行所有操作,内部采用了数据库事务;
|
||||
|
||||
```csharp
|
||||
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.MySql, connectionString)
|
||||
.UseAutoSyncStructure(true) //自动同步实体结构到数据库
|
||||
.Build(); //请务必定义成 Singleton 单例模式
|
||||
```
|
||||
|
||||
## 如何使用
|
||||
|
||||
```csharp
|
||||
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 实现多种事务传播](https://github.com/dotnetcore/FreeSql/issues/289)
|
||||
|
||||
## 接口定义
|
||||
|
||||
uow.GetOrBeginTransaction() 方法可获取事务对象。
|
||||
|
||||
```csharp
|
||||
public interface IUnitOfWork : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 该对象 Select/Delete/Insert/Update/InsertOrUpdate 与工作单元事务保持一致,可省略传递 WithTransaction
|
||||
/// </summary>
|
||||
IFreeSql Orm { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开启事务,或者返回已开启的事务
|
||||
/// </summary>
|
||||
/// <param name="isCreate">若未开启事务,则开启</param>
|
||||
/// <returns></returns>
|
||||
DbTransaction GetOrBeginTransaction(bool isCreate = true);
|
||||
|
||||
IsolationLevel? IsolationLevel { get; set; }
|
||||
|
||||
void Commit();
|
||||
|
||||
void Rollback();
|
||||
|
||||
/// <summary>
|
||||
/// 工作单元内的实体变化跟踪
|
||||
/// </summary>
|
||||
DbContext.EntityChangeReport EntityChangeReport { get; }
|
||||
}
|
||||
```
|
||||
|
||||
## 实体变化事件
|
||||
|
||||
全局设置:
|
||||
|
||||
```csharp
|
||||
fsql.SetDbContextOptions(opt => {
|
||||
opt.OnEntityChange = report => {
|
||||
Console.WriteLine(report);
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
单独设置:
|
||||
|
||||
```csharp
|
||||
var uow = fsql.CreateUnitOfWork();
|
||||
uow.OnEntityChange = report => {
|
||||
Console.WriteLine(report);
|
||||
};
|
||||
```
|
||||
|
||||
参数 report 是一个 List 集合,集合元素的类型定义如下:
|
||||
|
||||
```csharp
|
||||
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 方法,参数为表达式,而并非实体;
|
||||
```csharp
|
||||
int Delete(Expression<Func<TEntity, bool>> predicate);
|
||||
```
|
||||
|
||||
DbContext.SaveChanges,或者 Repository 对实体的 Insert/Update/Delete,或者 UnitOfWork.Commit 操作都会最多触发一次该事件。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [《租户》](%e7%a7%9f%e6%88%b7)
|
||||
- [《读写分离》](%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb)
|
||||
- [《分表、分库》](%e5%88%86%e8%a1%a8%e5%88%86%e5%ba%93)
|
||||
- [《仓储层Repository》](Repository)
|
||||
- [《过滤器、全局过滤器》](%e8%bf%87%e6%bb%a4%e5%99%a8)
|
||||
- [《AOP》](AOP)
|
||||
- [《DbContext》](DbContext)
|
||||
Reference in New Issue
Block a user