[Architect] Abp 框架原理解析 UnitOfWork

Posted 叶祖辉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Architect] Abp 框架原理解析 UnitOfWork相关的知识,希望对你有一定的参考价值。

本节目录

 

介绍

UOW(全称UnitOfWork)是指工作单元.

在Abp中,工作单元对于仓储和应用服务方法默认开启。并在一次请求中,共享同一个工作单元.

同时在Abp中,不仅支持同一个数据库连接,还支持事务处理.

 

分析Abp源码

1.UnitOfWorkRegistrar

 

2.ComponentRegistered

 

 

3.IsConventionalUowClass

 

 

4.Intercept

 

 

5.PerformSyncUow

 

 

 

实现UOW

定义IUnitOfWork

1
2
3
4
5
6
7
8
9
10
11
12
public interface IUnitOfWork
{
    //1.开启事务
    //2.设置Filter(本例中不做演示)
    void Begin(UnitOfWorkOptions options);
    void Complete();
}
public class UnitOfWorkOptions
{
    public bool? IsTransactional { getset; }
}

 

实现uow,在uow中会提供db的创建,这样才能管理到每个db.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class EfUnitOfWork : UnitOfWorkBase
{
    public static DbContext DbContext { getset; }
    public static DbContext GetDbContext()
    {
        if (DbContext == null)
        {
            DbContext = new DemoDb();
        }
        return DbContext;
    }
    public override void Begin(UnitOfWorkOptions options)
    {
        if (options.IsTransactional == true)
        {
            CurrentTransaction = new TransactionScope();
        }
    }
    public TransactionScope CurrentTransaction { getset; }
    public override void Complete()
    {
        SaveChanges();
        if (CurrentTransaction != null)
        {
            CurrentTransaction.Complete();
        }
    }
    private void SaveChanges()
    {
        DbContext.SaveChanges();
    }
}
public abstract class UnitOfWorkBase : IUnitOfWork
{
    public virtual void Begin(UnitOfWorkOptions options)
    {
    }
    public virtual void Complete()
    {
    }
}

 

定义与实现仓储层,这里不再做DbProvider.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface IRepository
{
}
public interface ITaskRepository : IRepository
{
    void Add(Task task);
}
public class TaskRepository : ITaskRepository
{
    public void Add(Task task)
    {
        var db = (DemoDb)EfUnitOfWork.GetDbContext();
        db.Tasks.Add(task);
    }
}

 

定义与实现应用层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface IApplicationService
{
}
public interface ITaskAppService : IApplicationService
{
    void CreateTask(CreateTaskInput input);
}
public class TaskAppService : ITaskAppService
{
    private ITaskRepository _repository;
    public TaskAppService(ITaskRepository repository)
    {
        _repository = repository;
    }
    public void CreateTask(CreateTaskInput input)
    {
        _repository.Add(new Task(input.Name));
    }
}
public class CreateTaskInput
{
    public string Name { getset; }
}

 

定义与实现uow拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
internal class UnitOfWorkInterceptor : IInterceptor
{
    private IUnitOfWork _unitOfWork;
    public UnitOfWorkInterceptor(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
    public void Intercept(IInvocation invocation)
    {
        _unitOfWork.Begin(new UnitOfWorkOptions());
        invocation.Proceed();
        _unitOfWork.Complete();
    }
}

 

定义在IApplicationService与IRepository接口下拦截

1
2
3
4
5
6
7
8
static void Kernel_ComponentRegistered(string key, Castle.MicroKernel.IHandler handler)
{
    var type = handler.ComponentModel.Implementation;
    if (typeof(IApplicationService).IsAssignableFrom(type) || typeof(IRepository).IsAssignableFrom(type))
    {
        handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor)));
    }
}

 

执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void Main(string[] args)
{
    using (var container = new WindsorContainer())
    {
        container.Register(Component.For<IInterceptor, UnitOfWorkInterceptor>());//先注入拦截器
        container.Register(Component.For<IUnitOfWork, EfUnitOfWork>());
        container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
        container.Register(Component.For<ITaskAppService, TaskAppService>());
        container.Register(Component.For<ITaskRepository, TaskRepository>());
        var person = container.Resolve<ITaskAppService>();
        person.CreateTask(new CreateTaskInput() { Name = "3333" });
    }
    Console.ReadKey();
}

 

会自动在application method的结尾调用Complete.

另外也可以在uow上定义option为启用事务.在本例中稍作扩展即可实现.

以上是关于[Architect] Abp 框架原理解析 UnitOfWork的主要内容,如果未能解决你的问题,请参考以下文章

[Architect] ABP(现代ASP.NET样板开发框架) 依赖注入

[Architect] ABP(现代ASP.NET样板开发框架) 介绍

[Architect] ABP(现代ASP.NET样板开发框架) Caching

[Architect] ABP(现代ASP.NET样板开发框架) 分层架构

ABP 框架测试中的“无法解析参数”错误

解析ABP框架中的事务处理和工作单元,ABP事务处理