ABP使用及框架解析系列 - [Unit of Work part.1-概念及使用]


前言

ABP

ABP是“ASP.NET Boilerplate Project”的簡稱。

ABP的官方網站:http://www.aspnetboilerplate.com

ABP在Github上的開源項目:https://github.com/aspnetboilerplate

ABP其他學習博客推薦及介紹:http://www.cnblogs.com/mienreal/p/4528470.html

 

Unit of Work

Unit of Work 又稱之為“工作單元”,Unit of Work的相關概念及介紹,請移步另一篇博客:設計模式/原則篇 - Unit of Work

在ABP中,因為不能確定開發人員實際使用的ORM和數據訪問層具體是什么,為了更好的擴展性,ABP為Unit of Work封裝了一套通用接口抽象,並提供了Entity Framework及NHibernate的實現。

 

使用

默認行為

在ABP中,ApplicationService(領域服務,實現IApplicationService接口的類)和Repository(實現IRepository接口的類)的每個方法默認都是一個工作單元。在方法的起始處就開始了一個事務,在方法的結束時,事務也會自動提交,如果這個方法中拋出了異常,事務會自動回滾。

public interface ISimpleAppService : IApplicationService
{
    void ComplexOperation();
}

public class SimpleAppService : ISimpleAppService
{
    public void ComplexOperation()
    {
        //該方法默認就是一個工作單元
    }
}


public interface ISimpleRepository : IRepository<Simple, string>
{
    List<Simple> GetAllByName(string name);
}

public class SimpleRepository : ABPRepositoryBase<Simple, long>, ISimpleRepository
{
    public List<Simple> GetAllByName(string name)
    {
        //該方法默認就是一個工作單元,ABPRepositoryBase默認有一些公共方法的實現,比如GetAll、Update這些
    }
}

 

UnitOfWorkAttribute

另一種添加Unit of Work的方式,便是在方法上面添加UnitOfWork特性,這樣便和上面的默認行為相同,該方法成為一個工作單元。

UnitOfWork特性,還包含一系列參數,Scope(事務參數)、IsTransactional(工作單元是否是事務)、Timeout(超時時間)、IsolationLevel(事務隔離級別)、IsDisabled(是否禁用工作單元,這個屬性用於關閉領域服務和倉儲庫默認的方法即工作單元的設置)。

public class TempService
{
    [UnitOfWork]
    public void Method()
    {
        //TempService不是領域服務,沒有實現IApplicationService接口,但是通過UnitOfWorkAttribute,使Method也成為一個工作單元
    }
}
重要

標記UnitOfWork特性的方法的所在類,需要注冊到IoC容器中,並通過IoC容器進行創建,類和方法的可訪問級別需要為public或protected,因為ABP通過動態代理實現AOP進行切面編程,具體緣由將在ABP使用及框架解析系列 - [Unit of Work part.2-框架實現]中解析。

 

IUnitOfWorkManager

上面兩種方式,其內部都是使用IUnitOfWorkManager進行單元控制的,所以我們也可以直接通過IUnitOfWorkManager進行控制,如下代碼所示:

public class TempService
{
    private IUnitOfWorkManager _uowManager;
    private ITempRepository _tempRsy;

    public TempService(IUnitOfWorkManager uowManager, ITempRepository tempRsy)
    {
        this._uowManager = uowManager;
        this._tempRsy = tempRsy;
    }

    public void Method()
    {
        using (var uow = _uowManager.Begin())
        {
            _tempRsy.Insert(new Temp());
            _tempRsy.Delete(1);

            uow.Complete();
        }
    }
}

TempService並非領域服務,沒有實現IApplicationService接口,所以Method方法默認不是一個工作單元。在Method內部,使用using塊便是一個工作單元,通過uow.Complete()進行提交,如果出現異常,會自動回滾。

IUnitOfWorkManager的Begin方法可接受一系列參數對工作單元或事務進行設置,在這里就不對每個參數進行詳細說明了。如有疑問,大家都已在評論中進行討論。

上述三種方式為Unit of Work在ABP中的使用方式,下面還有一些ABP中Unit of Work的特性、配置及注意事項。

 

全局/默認配置

不論是在使用Attribute還是IUnitOfWorkManager,都是可以進行一些參數設置的,但是同時也是可以不對其進行設置的,當不對其進行設置時,將會使用默認參數,而這個默認參數,可以通過一個全局配置進行修改。

ABP有一個IUnitOfWorkDefaultOptions接口,並且通過IoC與UnitOfWorkDefaultOptions進行了單例依賴注冊,所以通過IoC容器獲取IUnitOfWorkDefaultOptions實例時,可以獲取到Unit of Work全局默認配置,通過修改這個對象里的參數,可以修改其默認配置。但是需要注意的是,這個配置是一個全局配置,所以隨便在一個地方就進行修改不是一個好的做法。

ABP中有一個模塊(AbpModule)的概念,推薦在主項目的模塊類的PreInitialize方法中進行修改。ABP也為此提供了更加便捷的方式進行修改默認配置,AbpModule類下有一個Configuration屬性,該屬對象齊聚了很多配置項,其中UnitOfWork屬性便是IUnitOfWorkDefaultOptions接口對象,通過這個便可方便的修改默認配置了。

 

其他特性

1.支持多個工作單元嵌套,它們共用最外層的工作單元。但如果嵌套的工作單元在不同主線程上,則每個主線程會有一個不同的工作單元,具體實現將在ABP使用及框架解析系列 - [Unit of Work part.2-框架實現]中解析。

2.在工作單元中,進行數據查詢,如有返回IQueryable,需要再工作單元內進行ToList或ToArray等操作,因為返回IQueryable對象時並沒有進行真正的數據操作(延遲執行),而數據庫連接會在工作單元結束后關閉,所以如果再工作單元結束后進行ToList等操作,會拋出異常(當然,這里說的是ABP提供的NH和Ef的實現,自己實現ABP接口可以自行限制)。

3.Unit of Work除了提供了Complete外,還提供了SaveChanges方法,用於先行提交數據。在Entity主鍵為自增ID,並且后續操作需要這個ID時,可以通過先SaveChanges來提交數據來獲取自增ID值。

4.在使用ABP提供的EF實現中,在工作單元中對Entity進行修改后,即使不手動調用Update,在UoW結束時也會自動保存修改,因為Ef對Entity的狀態進行了跟蹤,並且在UoW進行Complete操作前,會先SaveChanges(NH沒有仔細研究)。

5.可以為Unit of Work注冊三個事件:Completed、Failed、Disposed。這三個事件,在IUnitOfWorkManager對象的Current屬性定義。

 

框架實現

由於框架實現內容較多,為了不導致篇幅過長,框架實現部分,請移步 ABP使用及框架解析系列 - [Unit of Work part.2-框架實現]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM