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

前言

ABP

ABP是「ASP.NET Boilerplate Project」的簡稱。html

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

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

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-框架實現]中解析。this

 

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-框架實現]

相關文章
相關標籤/搜索