解析ABP框架領(lǐng)域?qū)又械膶?shí)體類與倉(cāng)儲(chǔ)類
來(lái)源:易賢網(wǎng) 閱讀:1417 次 日期:2016-08-06 14:27:15
溫馨提示:易賢網(wǎng)小編為您整理了“解析ABP框架領(lǐng)域?qū)又械膶?shí)體類與倉(cāng)儲(chǔ)類”,方便廣大網(wǎng)友查閱!

基于ASP.NET的ABP框架遵循DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),其中就有一個(gè)領(lǐng)域?qū)拥母拍?這里我們就來(lái)解析ABP框架領(lǐng)域?qū)又械膶?shí)體類與倉(cāng)儲(chǔ)類:

領(lǐng)域?qū)?/P>

實(shí)體是DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))的核心概念之一。Eric Evans是這樣描述的“很多對(duì)象不是通過(guò)它們的屬性定義的,而是通過(guò)一連串的連續(xù)性事件和標(biāo)識(shí)定義的”(引用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)一書(shū))。

譯者注:對(duì)象不是通過(guò)它們的屬性來(lái)下根本性的定義,而應(yīng)該是通過(guò)它的線性連續(xù)性和標(biāo)識(shí)性定義的。。所以,實(shí)體是具有唯一標(biāo)識(shí)的ID且存儲(chǔ)在數(shù)據(jù)庫(kù)中。實(shí)體通常被映射成數(shù)據(jù)庫(kù)中的一個(gè)表。

實(shí)體類(Entity classes) 

在ABP中,實(shí)體繼承自Entity類,請(qǐng)看下面示例:

public class Person : Entity

{

  public virtual string Name { get; set; }

  public virtual DateTime CreationTime { get; set; }

  public Task()

  {

    CreationTime = DateTime.Now;

  }

}

Person 類被定義為一個(gè)實(shí)體。它具有兩個(gè)屬性,它的父類中有Id屬性。Id是該實(shí)體的主鍵。所以,Id是所有繼承自Entity類的實(shí)體的主鍵(所有實(shí)體的主鍵都是Id字段)。

Id(主鍵)數(shù)據(jù)類型可以被更改。默認(rèn)是int(int32)類型。如果你想給Id定義其它類型,你應(yīng)該像下面示例一樣來(lái)聲明Id的類型。

public class Person : Entity<long>

{

  public virtual string Name { get; set; }

  public virtual DateTime CreationTime { get; set; }

  public Task()

  {

    CreationTime = DateTime.Now;

  }

}

你可以設(shè)置為string,Guid或者其它數(shù)據(jù)類型。

實(shí)體類重寫了 equality (==) 操作符用來(lái)判斷兩個(gè)實(shí)體對(duì)象是否相等(兩個(gè)實(shí)體的Id是否相等)。還定義了一個(gè)IsTransient()方法來(lái)檢測(cè)實(shí)體是否有Id屬性。

接口約定

在很多應(yīng)用程序中,很多實(shí)體具有像CreationTime的屬性(數(shù)據(jù)庫(kù)表也有該字段)用來(lái)指示該實(shí)體是什么時(shí)候被創(chuàng)建的。APB提供了一些有用的接口來(lái)實(shí)現(xiàn)這些類似的功能。也就是說(shuō),為這些實(shí)現(xiàn)了這些接口的實(shí)體,提供了一個(gè)通用的編碼方式(通俗的說(shuō)只要實(shí)現(xiàn)指定的接口就能實(shí)現(xiàn)指定的功能)。

(1)審計(jì)(Auditing)

實(shí)體類實(shí)現(xiàn) IHasCreationTime 接口就可以具有CreationTime的屬性。當(dāng)該實(shí)體被插入到數(shù)據(jù)庫(kù)時(shí), ABP會(huì)自動(dòng)設(shè)置該屬性的值為當(dāng)前時(shí)間。

public interface IHasCreationTime

{

  DateTime CreationTime { get; set; }

}

Person類可以被重寫像下面示例一樣實(shí)現(xiàn)IHasCreationTime 接口:

public class Person : Entity<long>, IHasCreationTime

{

  public virtual string Name { get; set; }

  public virtual DateTime CreationTime { get; set; }

  public Task()

  {

    CreationTime = DateTime.Now;

  }

}

ICreationAudited 擴(kuò)展自 IHasCreationTime 并且該接口具有屬性 CreatorUserId :

public interface ICreationAudited : IHasCreationTime

{

  long? CreatorUserId { get; set; }

}

當(dāng)保存一個(gè)新的實(shí)體時(shí),ABP會(huì)自動(dòng)設(shè)置CreatorUserId 的屬性值為當(dāng)前用戶的Id

你可以輕松的實(shí)現(xiàn)ICreationAudited接口,通過(guò)派生自實(shí)體類 CreationAuditedEntity (因?yàn)樵擃愐呀?jīng)實(shí)現(xiàn)了ICreationAudited接口,我們可以直接繼承CreationAuditedEntity 類就實(shí)現(xiàn)了上述功能)。它有一個(gè)實(shí)現(xiàn)不同ID數(shù)據(jù)類型的泛型版本(默認(rèn)是int),可以為ID(Entity類中的ID)賦予不同的數(shù)據(jù)類型。

下面是一個(gè)為實(shí)現(xiàn)類似修改功能的接口

public interface IModificationAudited

{

  DateTime? LastModificationTime { get; set; }

  long? LastModifierUserId { get; set; }

}

當(dāng)更新一個(gè)實(shí)體時(shí),ABP會(huì)自動(dòng)設(shè)置這些屬性的值。你只需要在你的實(shí)體類里面實(shí)現(xiàn)這些屬性。

如果你想實(shí)現(xiàn)所有的審計(jì)屬性,你可以直接擴(kuò)展 IAudited 接口;示例如下:

public interface IAudited : ICreationAudited, IModificationAudited

{

}

作為一個(gè)快速開(kāi)發(fā)方式,你可以直接派生自AuditedEntity 類,不需要再去實(shí)現(xiàn)IAudited接口(AuditedEntity 類已經(jīng)實(shí)現(xiàn)了該功能,直接繼承該類就可以實(shí)現(xiàn)上述功能),AuditedEntity 類有一個(gè)實(shí)現(xiàn)不同ID數(shù)據(jù)類型的泛型版本(默認(rèn)是int),可以為ID(Entity類中的ID)賦予不同的數(shù)據(jù)類型。

(2)軟刪除(Soft delete)

軟刪除是一個(gè)通用的模式被用來(lái)標(biāo)記一個(gè)已經(jīng)被刪除的實(shí)體,而不是實(shí)際從數(shù)據(jù)庫(kù)中刪除記錄。例如:你可能不想從數(shù)據(jù)庫(kù)中硬刪除一條用戶記錄,因?yàn)樗辉S多其它的表所關(guān)聯(lián)。為了實(shí)現(xiàn)軟刪除的目的我們可以實(shí)現(xiàn)該接口 ISoftDelete:

public interface ISoftDelete{

  bool IsDeleted { get; set; }

}

ABP實(shí)現(xiàn)了開(kāi)箱即用的軟刪除模式。當(dāng)一個(gè)實(shí)現(xiàn)了軟刪除的實(shí)體正在被被刪除,ABP會(huì)察覺(jué)到這個(gè)動(dòng)作,并且阻止其刪除,設(shè)置IsDeleted 屬性值為true并且更新數(shù)據(jù)庫(kù)中的實(shí)體。也就是說(shuō),被軟刪除的記錄不可以從數(shù)據(jù)庫(kù)中檢索出,ABP會(huì)為我們自動(dòng)過(guò)濾軟刪除的記錄。(例如:Select查詢,這里指通過(guò)ABP查詢,不是通過(guò)數(shù)據(jù)庫(kù)中的查詢分析器查詢。)

如果你用了軟刪除,你有可能也想實(shí)現(xiàn)這個(gè)功能,就是記錄誰(shuí)刪除了這個(gè)實(shí)體。要實(shí)現(xiàn)該功能你可以實(shí)現(xiàn)IDeletionAudited 接口,請(qǐng)看下面示例:

public interface IDeletionAudited : ISoftDelete

{

  long? DeleterUserId { get; set; }

  DateTime? DeletionTime { get; set; }

}

正如你所看到的IDeletionAudited 擴(kuò)展自 ISoftDelete接口。當(dāng)一個(gè)實(shí)體被刪除的時(shí)候ABP會(huì)自動(dòng)的為這些屬性設(shè)置值。

如果你想為實(shí)體類擴(kuò)展所有的審計(jì)接口(例如:創(chuàng)建(creation),修改(modification)和刪除(deletion)),你可以直接實(shí)現(xiàn)IFullAudited接口,因?yàn)樵摻涌谝呀?jīng)繼承了這些接口,請(qǐng)看下面示例:

public interface IFullAudited : IAudited, IDeletionAudited

{

}

作為一個(gè)快捷方式,你可以直接從FullAuditedEntity 類派生你的實(shí)體類,因?yàn)樵擃愐呀?jīng)實(shí)現(xiàn)了IFullAudited接口。

注意:所有的審計(jì)接口和類都有一個(gè)泛型模板為了導(dǎo)航定義屬性到你的User 實(shí)體(例如:ICreationAudited<TUser>和FullAuditedEntity<TPrimaryKey, TUser>),這里的TUser指的進(jìn)行創(chuàng)建,修改和刪除的用戶的實(shí)體類的類型,詳細(xì)請(qǐng)看源代碼(Abp.Domain.Entities.Auditing空間下的FullAuditedEntity<TPrimaryKey, TUser>類),TprimaryKey 只的是Entity基類Id類型,默認(rèn)是int。

(3)激活狀態(tài)/閑置狀態(tài)(Active/Passive)

有些實(shí)體需要被標(biāo)記為激活狀態(tài)或者閑置狀態(tài)。那么你可以為實(shí)體采取active/passive狀態(tài)的行動(dòng)。基于這個(gè)原因而創(chuàng)建的實(shí)體,你可以擴(kuò)展IPassivable 接口來(lái)實(shí)現(xiàn)該功能。該接口定義了IsActive 的屬性。

如果你首次創(chuàng)建的實(shí)體被標(biāo)記為激活狀態(tài),你可以在構(gòu)造函數(shù)設(shè)置IsActive屬性值為true。

這是不同于軟刪除(IsDeleted)。如果實(shí)體被軟刪除,它不能從數(shù)據(jù)庫(kù)中被檢索到(ABP已經(jīng)過(guò)濾了軟刪除記錄)。但是對(duì)于激活狀態(tài)/閑置狀態(tài)的實(shí)體,你完全取決于你怎樣去獲取這些被標(biāo)記了的實(shí)體。

IEntity接口

事實(shí)上Entity 實(shí)現(xiàn)了IEntity 接口(和Entity<TPrimaryKey> 實(shí)現(xiàn)了 IEntity<TPrimaryKey>接口)。如果你不想從Entity 類派生,你能直接的實(shí)現(xiàn)這些接口。其他實(shí)體類也可以實(shí)現(xiàn)相應(yīng)的接口。但是不建議你用這種方式。除非你有一個(gè)很好的理由不從Entity 類派生。

倉(cāng)儲(chǔ)(Repositories)

倉(cāng)儲(chǔ)定義:“在領(lǐng)域?qū)雍蛿?shù)據(jù)映射層的中介,使用類似集合的接口來(lái)存取領(lǐng)域?qū)ο蟆?Martin Fowler)。

實(shí)際上,倉(cāng)儲(chǔ)被用于領(lǐng)域?qū)ο笤跀?shù)據(jù)庫(kù)上的操作(實(shí)體Entity和值對(duì)象Value types)。一般來(lái)說(shuō),我們針對(duì)不同的實(shí)體(或聚合根Aggregate Root)會(huì)創(chuàng)建相對(duì)應(yīng)的倉(cāng)儲(chǔ)。

IRepository接口 

在ABP中,倉(cāng)儲(chǔ)類要實(shí)現(xiàn)IRepository接口。最好的方式是針對(duì)不同倉(cāng)儲(chǔ)對(duì)象定義各自不同的接口。

針對(duì)Person實(shí)體的倉(cāng)儲(chǔ)接口聲明的示例如下所示:

public interface IPersonRepository : IRepository<Person> 

{

}

IPersonRepository繼承自IRepository<TEntity>,用來(lái)定義Id的類型為int(Int32)的實(shí)體。如果你的實(shí)體Id數(shù)據(jù)類型不是int,你可以繼承IRepository<TEntity, TPrimaryKey>接口,如下所示:

public interface IPersonRepository : IRepository<Person, long> 

}

對(duì)于倉(cāng)儲(chǔ)類,IRepository定義了許多泛型的方法。比如: Select,Insert,Update,Delete方法(CRUD操作)。在大多數(shù)的時(shí)候,這些方法已足已應(yīng)付一般實(shí)體的需要。如果這些方對(duì)于實(shí)體來(lái)說(shuō)已足夠,我們便不需要再去創(chuàng)建這個(gè)實(shí)體所需的倉(cāng)儲(chǔ)接口/類。在Implementation章節(jié)有更多細(xì)節(jié)。

(1)查詢(Query)

IRepository定義了從數(shù)據(jù)庫(kù)中檢索實(shí)體的常用方法。

A、取得單一實(shí)體(Getting single entity):

TEntity Get(TPrimaryKey id);

Task<TEntity> GetAsync(TPrimaryKey id);

TEntity Single(Expression<Func<TEntity, bool>> predicate);

TEntity FirstOrDefault(TPrimaryKey id);

Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id);

TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);

Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);

TEntity Load(TPrimaryKey id);

Get方法被用于根據(jù)主鍵值(Id)取得對(duì)應(yīng)的實(shí)體。當(dāng)數(shù)據(jù)庫(kù)中根據(jù)主鍵值找不到相符合的實(shí)體時(shí),它會(huì)拋出例外。Single方法類似Get方法,但是它的輸入?yún)?shù)是一個(gè)表達(dá)式而不是主鍵值(Id)。因此,我們可以寫Lambda表達(dá)式來(lái)取得實(shí)體。示例如下:

var person = _personRepository.Get(42);

var person = _personRepository.Single(p => o.Name == "Halil ibrahim Kalkan");

注意,Single方法會(huì)在給出的條件找不到實(shí)體或符合的實(shí)體超過(guò)一個(gè)以上時(shí),都會(huì)拋出例外。

FirstOrDefault也一樣,但是當(dāng)沒(méi)有符合Lambda表達(dá)式或Id的實(shí)體時(shí),會(huì)回傳null(取代拋出異常)。當(dāng)有超過(guò)一個(gè)以上的實(shí)體符合條件,它只會(huì)返回第一個(gè)實(shí)體。

Load并不會(huì)從數(shù)據(jù)庫(kù)中檢索實(shí)體,但它會(huì)創(chuàng)建延遲執(zhí)行所需的代理對(duì)象。如果你只使用Id屬性,實(shí)際上并不會(huì)檢索實(shí)體,它只有在你存取想要查詢實(shí)體的某個(gè)屬性時(shí)才會(huì)從數(shù)據(jù)庫(kù)中查詢實(shí)體。當(dāng)有性能需求的時(shí)候,這個(gè)方法可以用來(lái)替代Get方法。Load方法在NHibernate與ABP的整合中也有實(shí)現(xiàn)。如果ORM提供者(Provider)沒(méi)有實(shí)現(xiàn)這個(gè)方法,Load方法運(yùn)行的會(huì)和Get方法一樣。

ABP有些方法具有異步(Async)版本,可以應(yīng)用在異步開(kāi)發(fā)模型上(見(jiàn)Async方法相關(guān)章節(jié))。

B、取得實(shí)體列表(Getting list of entities):

List<TEntity> GetAllList();

Task<List<TEntity>> GetAllListAsync();

List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate);

Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);

IQueryable<TEntity> GetAll();

GetAllList被用于從數(shù)據(jù)庫(kù)中檢索所有實(shí)體。重載并且提供過(guò)濾實(shí)體的功能,如下:

var allPeople = _personRespository.GetAllList();

var somePeople = _personRepository.GetAllList(person => person.IsActive && person.Age > 42);

GetAll返回IQueryable<T>類型的對(duì)象。因此我們可以在調(diào)用完這個(gè)方法之后進(jìn)行Linq操作。示例:

//例子一

var query = from person in _personRepository.GetAll()

where person.IsActive

orderby person.Name

select person;

var people = query.ToList();

//例子二

List<Person> personList2 = _personRepository.GetAll().Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).Skip(40).Take(20).ToList();

 如果調(diào)用GetAll方法,那么幾乎所有查詢都可以使用Linq完成。甚至可以用它來(lái)編寫Join表達(dá)式。

說(shuō)明:關(guān)于IQueryable<T>

當(dāng)你調(diào)用GetAll這個(gè)方法在Repository對(duì)象以外的地方,必定會(huì)開(kāi)啟數(shù)據(jù)庫(kù)連接。這是因?yàn)镮Queryable<T>允許延遲執(zhí)行。它會(huì)直到你調(diào)用ToList方法或在forEach循環(huán)上(或是一些存取已查詢的對(duì)象方法)使用IQueryable<T>時(shí),才會(huì)實(shí)際執(zhí)行數(shù)據(jù)庫(kù)的查詢。因此,當(dāng)你調(diào)用ToList方法時(shí),數(shù)據(jù)庫(kù)連接必需是啟用狀態(tài)。我們可以使用ABP所提供的UnitOfWork特性在調(diào)用的方法上來(lái)實(shí)現(xiàn)。注意,Application Service方法預(yù)設(shè)都已經(jīng)是UnitOfWork。因此,使用了GetAll方法就不需要如同Application Service的方法上添加UnitOfWork特性。

有些方法擁有異步版本,可應(yīng)用在異步開(kāi)發(fā)模型(見(jiàn)關(guān)于async方法章節(jié))。

自定義返回值(Custom return value)

ABP也有一個(gè)額外的方法來(lái)實(shí)現(xiàn)IQueryable<T>的延遲加載效果,而不需要在調(diào)用的方法上添加UnitOfWork這個(gè)屬性卷標(biāo)。

T Query<T>(Func<IQueryable<Tentity>,T> queryMethod);

查詢方法接受Lambda(或一個(gè)方法)來(lái)接收IQueryable<T>并且返回任何對(duì)象類型。示例如下:

var  people = _personRepository.Query(q => q.Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).ToList());

因?yàn)槭遣捎肔ambda(或方法)在倉(cāng)儲(chǔ)對(duì)象的方法中執(zhí)行,它會(huì)在數(shù)據(jù)庫(kù)連接開(kāi)啟之后才被執(zhí)行。你可以返回實(shí)體集合,或一個(gè)實(shí)體,或一個(gè)具部份字段(注: 非Select *)或其它執(zhí)行查詢后的查詢結(jié)果集。

(2)新增(insert)

IRepository接口定義了簡(jiǎn)單的方法來(lái)提供新增一個(gè)實(shí)體到數(shù)據(jù)庫(kù):

TEntity Insert(TEntity entity);

Task<TEntity> InsertAsync(TEntity entity);

TPrimaryKey InsertAndGetId(TEntity entity);

Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity);

TEntity InsertOrUpdate(TEntity entity);

Task<TEntity> InsertOrUpdateAsync(TEntity entity);

TPrimaryKey InsertOrUpdateAndGetId(TEntity entity);

Task<TPrimaryKey> InsertOrUpdateAndGetIdAsync(TEntity entity);

新增方法會(huì)新增實(shí)體到數(shù)據(jù)庫(kù)并且返回相同的已新增實(shí)體。InsertAndGetId方法返回新增實(shí)體的標(biāo)識(shí)符(Id)。當(dāng)我們采用自動(dòng)遞增標(biāo)識(shí)符值且需要取得實(shí)體的新產(chǎn)生標(biāo)識(shí)符值時(shí)非常好用。InsertOfUpdate會(huì)新增或更新實(shí)體,選擇那一種是根據(jù)Id是否有值來(lái)決定。最后,InsertOrUpdatedAndGetId會(huì)在實(shí)體被新增或更新后返回Id值。

所有的方法都擁有異步版本可應(yīng)用在異步開(kāi)發(fā)模型(見(jiàn)關(guān)于異步方法章節(jié))

(3)更新(UPDATE)

IRepository定義一個(gè)方法來(lái)實(shí)現(xiàn)更新一個(gè)已存在于數(shù)據(jù)庫(kù)中的實(shí)體。它更新實(shí)體并返回相同的實(shí)體對(duì)象。

TEntity Update(TEntity entity);

Task<TEntity> UpdateAsync(TEntity entity);

(4)刪除(Delete)

IRepository定了一些方法來(lái)刪除已存在數(shù)據(jù)庫(kù)中實(shí)體。

void Delete(TEntity entity);

Task DeleteAsync(TEntity entity);

void Delete(TPrimaryKey id);

Task DeleteAsync(TPrimaryKey id);

void Delete(Expression<Func<TEntity, bool>> predicate);

Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);

第一個(gè)方法接受一個(gè)現(xiàn)存的實(shí)體,第二個(gè)方法接受現(xiàn)存實(shí)體的Id。

最后一個(gè)方法接受一個(gè)條件來(lái)刪除符合條件的實(shí)體。要注意,所有符合predicate表達(dá)式的實(shí)體會(huì)先被檢索而后刪除。因此,使用上要很小心,這是有可能造成許多問(wèn)題,假如果有太多實(shí)體符合條件。

所有的方法都擁有async版本來(lái)應(yīng)用在異步開(kāi)發(fā)模型(見(jiàn)關(guān)于異步方法章節(jié))。

(5)其它方法(others)

IRepository也提供一些方法來(lái)取得數(shù)據(jù)表中實(shí)體的數(shù)量。

int Count();

Task<int> CountAsync();

int Count(Expression<Func<TEntity, bool>> predicate);

Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);

Long LongCount();

Task<long> LongCountAsync();

Long LongCount(Expression<Func<TEntity, bool>> predicate);

Task<long> LongCountAsync(Expression<TEntity, bool>> predicate);

所有的方法都擁有async版本被應(yīng)用在異步開(kāi)發(fā)模型(見(jiàn)關(guān)于異步方法章節(jié))。

(6)關(guān)于異步方法(About Async methods)

ABP支持異步開(kāi)發(fā)模型。因此,倉(cāng)儲(chǔ)方法擁有Async版本。在這里有一個(gè)使用異步模型的application service方法的示例:

public class PersonAppService : AbpWpfDemoAppServiceBase, IPersonAppService

{

  private readonly IRepository<Person> _personRepository;

  public PersonAppService(IRepository<Person> personRepository)

  {

    _personRepository = personRepository;

  }

  public async Task<GetPeopleOutput> GetAllPeople()

  {

    var people = await _personRepository.GetAllListAsync();

    return new GetPeopleOutput

    {

      People = Mapper.Map<List<PersonDto>>(people)

    };

  }

}

GetAllPeople方法是異步的并且使用GetAllListAsync與await保留關(guān)鍵字。

Async不是在每個(gè)ORM框架都有提供。

上例是從EF所提供的異步能力。如果ORM框架沒(méi)有提供Async的倉(cāng)儲(chǔ)方法則它會(huì)以同步的方式操作。同樣地,舉例來(lái)說(shuō),InsertAsync操作起來(lái)和EF的新增是一樣的,因?yàn)镋F會(huì)直到單元作業(yè)(unit of work)完成之后才會(huì)寫入新實(shí)體到數(shù)據(jù)庫(kù)中(DbContext.SaveChanges)。

倉(cāng)儲(chǔ)的實(shí)現(xiàn)

ABP在設(shè)計(jì)上是采取不指定特定ORM框架或其它存取數(shù)據(jù)庫(kù)技術(shù)的方式。只要實(shí)現(xiàn)IRepository接口,任何框架都可以使用。

倉(cāng)儲(chǔ)要使用NHibernate或EF來(lái)實(shí)現(xiàn)都很簡(jiǎn)單。

EntityFramework

當(dāng)你使用NHibernate或EntityFramework,如果提供的方法已足夠使用,你就不需要為你的實(shí)體創(chuàng)建倉(cāng)儲(chǔ)對(duì)象了。我們可以直接注入IRepository<TEntity>(或IRepository<TEntity, TPrimaryKey>)。下面的示例為application service使用倉(cāng)儲(chǔ)對(duì)象來(lái)新增實(shí)體到數(shù)據(jù)庫(kù):

public class PersonAppService : IPersonAppService

{

  private readonly IRepository<Person> _personRepository;

  public PersonAppService(IRepository<Person> personRepository)

  {

    _personRepository = personRepository;

  }

  public void CreatePerson(CreatePersonInput input)

  {    

    person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };

    _personRepository.Insert(person);

  }

}

 PersonAppService的建構(gòu)子注入了IRepository<Person>并且使用其Insert方法。當(dāng)你有需要為實(shí)體創(chuàng)建一個(gè)客制的倉(cāng)儲(chǔ)方法,那么你就應(yīng)該創(chuàng)建一個(gè)倉(cāng)儲(chǔ)類給指定的實(shí)體。

管理數(shù)據(jù)庫(kù)連接

數(shù)據(jù)庫(kù)連接的開(kāi)啟和關(guān)閉,在倉(cāng)儲(chǔ)方法中,ABP會(huì)自動(dòng)化的進(jìn)行連接管理。

當(dāng)倉(cāng)儲(chǔ)方法被調(diào)用后,數(shù)據(jù)庫(kù)連接會(huì)自動(dòng)開(kāi)啟且啟動(dòng)事務(wù)。當(dāng)倉(cāng)儲(chǔ)方法執(zhí)行結(jié)束并且返回以后,所有的實(shí)體變化都會(huì)被儲(chǔ)存, 事務(wù)被提交并且數(shù)據(jù)庫(kù)連接被關(guān)閉,一切都由ABP自動(dòng)化的控制。如果倉(cāng)儲(chǔ)方法拋出任何類型的異常,事務(wù)會(huì)自動(dòng)地回滾并且數(shù)據(jù)連接會(huì)被關(guān)閉。上述所有操作在實(shí)現(xiàn)了IRepository接口的倉(cāng)儲(chǔ)類所有公開(kāi)的方法中都可以被調(diào)用。

如果倉(cāng)儲(chǔ)方法調(diào)用其它倉(cāng)儲(chǔ)方法(即便是不同倉(cāng)儲(chǔ)的方法),它們共享同一個(gè)連接和事務(wù)。連接會(huì)由倉(cāng)儲(chǔ)方法調(diào)用鏈最上層的那個(gè)倉(cāng)儲(chǔ)方法所管理。更多關(guān)于數(shù)據(jù)庫(kù)管理,詳見(jiàn)UnitOfWork文件。

儲(chǔ)的生命周期

所有的倉(cāng)儲(chǔ)對(duì)象都是暫時(shí)性的。這就是說(shuō),它們是在有需要的時(shí)候才會(huì)被創(chuàng)建。ABP大量的使用依賴注入,當(dāng)倉(cāng)儲(chǔ)類需要被注入的時(shí)候,新的類實(shí)體會(huì)由注入容器會(huì)自動(dòng)地創(chuàng)建。見(jiàn)相根據(jù)注入文件有更多信息。

倉(cāng)儲(chǔ)的最佳實(shí)踐

對(duì)于一個(gè)T類型的實(shí)體,是可以使用IRepository<T>。但別任何情況下都創(chuàng)建定制化的倉(cāng)儲(chǔ),除非我們真的很需要。預(yù)定義倉(cāng)儲(chǔ)方法已經(jīng)足夠應(yīng)付各種案例。

假如你正創(chuàng)建定制的倉(cāng)儲(chǔ)(可以實(shí)現(xiàn)IRepository<TEntity>)

倉(cāng)儲(chǔ)類應(yīng)該是無(wú)狀態(tài)的。這意味著, 你不該定義倉(cāng)儲(chǔ)等級(jí)的狀態(tài)對(duì)象并且倉(cāng)儲(chǔ)方法的調(diào)用也不應(yīng)該影響到其它調(diào)用。    

當(dāng)倉(cāng)儲(chǔ)可以使用相根據(jù)注入,盡可較少或是不相根據(jù)于其它服務(wù)?!?/P>

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65317125(9:00—18:00) 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)