概述
基礎設施層是整個系統的?持層,通過對第三?類庫的調?或系統的抽象和集成來實現對其他層的?持。
與傳統架構不同在DDD中,數據庫訪問的具體實現(倉儲)也被放在了基礎設施層。
在DDD的理念中,基礎設施層是為領域和用例的邏輯實現提供支撐。在前面的章節我也提到,在DDD的理念中,數據訪問具體實現不是設計過程需要關注的重點,所以將具體訪問數據庫的代碼放在了基礎設施層。
概覽
通常情況下,我們會將提供數據服務連接的相關類和方法存放于一個項目中,而將其他公共類,公共方法存放于另外的一個或多個項目中。這些自定義的公共類庫,這里我就不具體講述,請依據個人項目需要來進行規劃設計。
基礎設施層數據庫連接服務主要包含以下組件:
倉儲(Repository)實現:對領域層定義的倉儲接口的實現類,用戶封裝對領域對象的數據持久化操作的具體實現。
在ABP框架下,基礎設施層提供數據庫訪問的類庫包含應用程序的數據庫上下文(DbContext)、數據庫映射、倉儲的實現等信息。依據項目需要,我們可以通過CLI中的?-d?參數來選擇使用EF Core或者MongoDB,分別會包含以下兩個類庫:
EntityFrameworkCore:是EF Core的基本集成包,支持SQL Server、MySQL、SQLite、Oracle、PostgreSQL數據庫。默認使用SQL Server數據庫。
MongoDB:以MongoDB為數據庫的基礎設施層類庫。
實現細節
1
默認倉儲
ABP提供了用于實體增刪改查的默認倉儲接口和實現類,在大多數情況下,我們只需要直接注入使用默認倉儲?IRepository<TEntity, TKey>?即可,其中TEntity為需要操作的實體,TKey為該實體主鍵的數據類型。
使用默認倉儲時,需要在EntityFrameworkCore項目的Module類中的?ConfigureServices?方法中加入以下代碼用于給所有實體創建默認倉儲:
context.Services.AddAbpDbContext<MyDbContext>(options =>{options.AddDefaultRepositories(includeAllEntities: true);});
其中MyDbContext為當前項目的數據上下文,includeAllEntities參數為true時會給所有實體、聚合根創建默認倉儲,如果為false則只給聚合根創建默認倉儲。
在默認倉儲中,ABP提供了以下方法可供直接操作數據庫:
GetAsync:通過lambda 表達式查詢單個實體,如果存在多個滿足條件的實體,則拋出?InvalidOperationException?異常。
FindAsync:通過lambda 表達式查詢單個實體,如果存在多個滿足條件的實體,則拋出?InvalidOperationException?異常。
InsertAsync:添加實體。
InsertManyAsync:批量添加。
UpdateAsync:更新實體。
UpdateManyAsync:批量修改。
DeleteAsync:刪除實體,也可根據Lambda表達式刪除。
DeleteManyAsync:批量刪除。
GetListAsync:獲取數據庫中所有實體的列表。
GetPagedListAsync:分頁獲取實體集合。
GetCountAsync:獲取數據庫中所有實體的計數。
GetAsync方法和FindAsync方法的區別為:如果實體未找到,GetAsync拋出?EntityNotFoundException?異常,而FindAsync方法返回?null?
另外,在很多情況下,我們希望獲取?IQueryable?類型用于自定義Linq查詢,在ABP 5.0版本之后,獲取IQueryable方式改為?await?_personRepository.GetQueryableAsync();?
2
自定義倉儲
如果默認倉儲不能滿足我們的需求,我們可以自定義倉儲接口和實現。
自定義倉儲接口聲明存放與領域層,可繼承自?IRepository<TEntity,TKey>?,其實現類存放與基礎設施層,繼承自?EfCoreRepository<TDbContext,TEntity,TKey>?或?MongoDbRepository<TDbContext, TEntity, TKey>?
3
Dapper集成
在一些情況下,我們希望可以使用自定義的SQL語句進行更靈活的數據庫操作或者執行存儲過程調用等操作,而Dapper框架可以滿足我們需求。
在ABP,Dapper框架并被沒有完整的集成,而是依托于EF Core實現。也就意味著如果要使用Dapper,創建項目時,數據訪問對象依舊選擇EF Core。
當使用Dapper時,我們需要創建自定義倉儲,并將其實現類繼承自?DapperRepository<TDbContext>?,其中TDbContext為EF Core項目的數據上下文。
具體用法,我們可以參考官方提供的示例:
public class PersonDapperRepository : DapperRepository<MyAppDbContext>, ITransientDependency
{public PersonDapperRepository(IDbContextProvider<MyAppDbContext> dbContextProvider): base(dbContextProvider){}public virtual async Task<List<string>> GetAllPersonNames(){var dbConnection = await GetDbConnectionAsync();return (await dbConnection.QueryAsync<string>("select Name from People", transaction: await GetDbTransactionAsync())).ToList();}public virtual async Task<int> UpdatePersonNames(string name){var dbConnection = await GetDbConnectionAsync();return await dbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name },await GetDbTransactionAsync());}
}
歡迎加入微信交流群
END
關注我獲得
更多精彩