實現倉儲

tkbSimplest發表於2015-11-01

返回總目錄《一步一步使用ABP框架搭建正式專案系列教程》


這一節我們來實現上一節定義的倉儲介面。

上一節是在領域層定義的倉儲介面,但是需要注意的是,實現這些倉儲介面是在基礎設施層,在我的專案中就是EntityFramework層。這樣做的好處就是領域層完全獨立於基礎設施層,耦合程度大大降低。

上一節我們定義了一個ICityRepository倉儲介面,所以接下來我們來實現它。現在我們找到基礎設施層名為“Repositories”的資料夾,在這裡面存放實現倉儲介面的類。這個資料夾是ABP模板自動幫我們生成的,而且可以它看到還有一個父目錄EntityFramework。本目錄下ABP模板已經幫我們建立了一個倉儲基類“ChargeStationRepositoryBase”,以後如果我們要給倉儲實現新增公共的方法時,就可以直接新增到該基類中。父目錄下有一個之前講過的資料庫上下文類的子類。

image

接下來,在Repositories資料夾裡定義ICityRepository的實現類CityRepository,程式碼如下:

namespace Noah.ChargeStation.EntityFramework.Repositories
{
    public class CityRepository:ChargeStationRepositoryBase<Cities>,ICityRepository
    {
        public CityRepository(IDbContextProvider<ChargeStationDbContext> dbContextProvider):base(dbContextProvider)
        {
            
        }
        public List<Cities> GetCitiesWithProvince(string provinceCode)
        {
            var query = GetAll();//GetAll()返回一個IQueryable<T>,我們可以通過它來查詢
              var query2 = Context.Cities.AsQueryable();//也可以直接使用EF的DbContext物件
              var query3 = Table.AsQueryable();//另一種選擇:直接使用Table屬性代替"Context.Cities",都是一樣的。
              if (!string.IsNullOrEmpty(provinceCode))
            {
                query = query.Where(c => c.ProvinceCode == provinceCode);
            }
            return query.ToList();
        }
    }
}

CityRepository繼承了泛型的ChargeStationRepositoryBase類,而且實現了倉儲介面。這裡要顯示宣告實現類的有引數的建構函式,使用泛型的IDbContextProvider將資料庫上下文的子類ChargeStationContext傳給父類的建構函式。

GetCitiesWithProvince(…)方法是我們實現倉儲介面ICityRepository中的方法,也是我們自己特殊需要的方法。

在倉儲中,我們可以自由地使用Context(EF的DbContext)物件和資料庫。ABP框架為我們管理資料庫連線,事務,建立和釋放DbContext,因而不用我們自己處理了。

這裡我們也可以定義一個非同步版本的方法,功能和上面的方法相同(關於非同步的部落格,可以看我的目錄《C#非同步程式設計》):

        public async Task<List<Cities>> GetCitiesWithProvinceAsync(string provinceCode)
        {
            return await GetAllListAsync(c => c.ProvinceCode == provinceCode);
        }

這裡注意一下GetAll()方法和GetAllList()方法的區別:前者返回的型別是IQueryable<T>,後者是List<T>。說到這裡又不得不說下IQueryable<T>和List<T>的區別。

IQueryable<T>:

當你在Repository物件以外的地方呼叫GetAll這個方法,必定會開啟資料庫連線。這是因為IQueryable<T>允許延遲執行。只有在IQueryable<T>(或一些存取已查詢的物件方法)上使用ToList()或foreach()迭代IQueryable<T>時,才會實際執行資料庫的查詢。因此,當你呼叫ToList方法時,資料庫連線必需是啟用狀態。我們可以使用ABP所提供的UnitOfWork特性在呼叫的方法上來實現。注意,Application Service方法預設都已經是UnitOfWork。因此,使用了GetAll方法就不需要如同Application Service的方法上新增UnitOfWork特性。

List<T>:

返回的該結果說明已經執行了資料庫查詢或者已經從記憶體中取出了資料(如果記憶體中有的話)。

好的,今天的實現倉儲就講到這,下一次說《構建應用層服務》。

相關文章