返回ABP系列html
ABP是「ASP.NET Boilerplate Project (ASP.NET樣板項目)」的簡稱。git
ASP.NET Boilerplate是一個用最佳實踐和流行技術開發現代WEB應用程序的新起點,它旨在成爲一個通用的WEB應用程序框架和項目模板。github
ABP的官方網站:http://www.aspnetboilerplate.com數據庫
ABP官方文檔:http://www.aspnetboilerplate.com/Pages/Documents框架
Github上的開源項目:https://github.com/aspnetboilerplate函數
實體是DDD(領域驅動設計)的核心概念之一。Eirc Evans是這樣描述的實體的:「它根本上不是經過屬性定義的,而是經過一系列連續性和標識定義的」。所以,實體都有Id屬性而且都存儲到數據庫中。一個實體通常會映射到數據庫的一張表。源碼分析
一、實體類網站
在ABP中,實體派生自Entity類,例如:ui
public class Person : Entity { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
上面定義了一個Person實體類,並且在Entity類中定義了一個Id屬性,它是該Entity類的主鍵。所以,全部實體的主鍵名都是相同的,都是Id。編碼
主鍵Id的類型是能夠改變的,默認是int(int32)的。若是你想將Id定義爲其餘類型,能夠像下面那樣顯示聲明:
public class Person : Entity<long> { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
主鍵Id也能夠設置爲string,Guid或其餘類型的。
Entity類重寫了等號運算符(==),能夠輕鬆地檢查兩個實體是否相同了(實體的Id相同則認爲它們相同)。它也定義了IsTransient方法來檢測它是否有Id。
二、接口約定
在不少應用程序中,不少實體具備像CreationTime的屬性(數據庫表也有該字段)用來指示該實體是何時被建立的。APB提供了一些有用的接口來實現這些相似的功能。也就是說,爲這些實現了這些接口的實體,提供了一個通用的編碼方式(通俗的說只要實現指定的接口就能實現指定的功能)。
1)、審計
實體類實現 IHasCreationTime 接口就能夠具備CreationTime的屬性。當該實體被插入到數據庫時, ABP會自動設置該屬性的值爲當前時間。
public interface IHasCreationTime { DateTime CreationTime { get; set; } }
Person類能夠經過實現IHasCreationTime接口來重寫,以下:
public class Person : Entity<long>, IHasCreationTime { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
ICreationAudited經過增長了CreatorUserId擴展了IHasCreationTime:
public interface ICreationAudited : IHasCreationTime { long? CreatorUserId { get; set; } }
當保存一個新的實體時,ABP會自動地將當前的用戶Id設置爲CreatorUserId。
你也能夠經過從CreationAuditedEntity類派生實體,從而輕易地實現ICreationAudited。
對於修改也有類似的接口:
public interface IModificationAudited { DateTime? LastModificationTime { get; set; } long? LastModifierUserId { get; set; } }
做爲一個快捷方式,你能夠從AuditedEntity類派生,而不須要直接實現IAudited。AuditedEntity類對於不一樣類型的Id屬性也有泛型的版本。
2)、軟刪除
軟刪除是一個通用的模式被用來標記一個已經被刪除的實體,而不是實際從數據庫中刪除記錄。例如:你可能不想從數據庫中硬刪除一條用戶記錄,由於它被許多其它的表所關聯。爲了實現軟刪除的目的咱們能夠實現該接口 ISoftDelete:
public interface ISoftDelete{ bool IsDeleted { get; set; } }
ABP實現了開箱即用的軟刪除模式。當一個軟刪除實體被刪除後,ABP檢測到以後,會阻止刪除,將IsDeleted設置爲true並更新數據庫中的實體。並且,它會自動地過濾數據庫中軟刪除的實體,不會檢索(select)它們。
若是你用了軟刪除,你有可能也想實現這個功能,就是記錄誰刪除了這個實體。要實現該功能你能夠實現IDeletionAudited 接口,請看下面示例:
public interface IDeletionAudited : ISoftDelete { long? DeleterUserId { get; set; } DateTime? DeletionTime { get; set; } }
IDeletionAudited擴展了ISoftDelete,當刪除一個實體時,ABP會自動設置這些屬性。
若是你想爲一個實體實現全部的審計接口(建立,修改和刪除),那麼能夠直接實現IFullAudited,由於它繼承了全部的這些接口:
public interface IFullAudited : IAudited, IDeletionAudited { }
做爲一個快捷方式,你能夠直接從FullAuditedEntity 類派生你的實體類,由於該類已經實現了IFullAudited接口。
注意:全部的審計接口和類都有一個定義導航屬性到User實體的泛型版本(好比ICreationAudited和FullAuditedEntity<tprimarykey,tuser>)。
3)、激活/未激活
一些實體須要標記爲激活的或未激活的。這樣,你就能夠根據實體的激活或者未激活狀態來採起行動。你能夠實現IPassivable接口來達到目的。該接口定義了IsActive屬性。
若是實體在第一次建立時是激活的,那麼你能夠在構造函數中將IsActive設置爲true。
這與軟刪除(IsDeleted)是不一樣的。若是一個實體是軟刪除的,那麼它就不會從數據庫中檢索到了(ABP默認會阻止),可是,對於激活或者未激活的實體,控制獲取實體徹底取決於你。
二、IEntity接口
實際上,Entity類實現了IEntity接口(且Entity實現了IEntity)。若是不想從Entity類中派生,那麼能夠直接實現這些接口。可是,除非你有一個好的緣由不從Entity類派生,不然,不建議這麼作。
代碼:
部分類圖:
IEntity<TPrimaryKey>: 封裝了PrimaryKey:Id,這是一個泛型類型
IEntity: 封裝了PrimaryKey:Id,這是一個int類型
Entity<TPrimaryKey> :支持主鍵是泛型類型的Entity
Entity:支持主鍵是int類型的Entity
IHasCreationTime: 封裝了CreationTime
ICreationAudited: 封裝了CreatorUserId,這個是long類型
CreationAuditedEntity<TPrimaryKey> : 支持主鍵是泛型類型的Entity,而且封裝了CreationTime 和 CreatorUserId
CreationAuditedEntity: 只支持主鍵是int類型的Entity,而且封裝了CreationTime 和 CreatorUserId
ICreationAudited<TUser> :封裝了泛型類型的creator
CreationAuditedEntity<TPrimaryKey, TUser> : 支持主鍵是泛型類型,而且封裝了泛型類型的creator的Entity
ISoftDelete:封裝了軟刪除的標誌IsDeleted
IHasDeletionTime:封裝了DeletionTime
IDeletionAudited:封裝了DeleterUserId,這個是long類型
IDeletionAudited: 封裝了泛型類型的DeleterUser
IHasModificationTime:封裝了LastModificationTime
IModificationAudited: 封裝了LastModifierUserId,這個是long類型
IModificationAudited<TUser> : 封裝了泛型類型的LastModifierUser
IAudited:從其父類接口那繼承了Creation 和 Modification 的時間和UserID,這個是long類型
AuditedEntity<TPrimaryKey> :支持主鍵是泛型類型的Entity,而且從其父類接口那繼承了Creation 和 Modification 的時間和UserID,這個是long類型
AuditedEntity: 與AuditedEntity<TPrimaryKey>的區別就是其只支持主鍵是int類型的Entity。
AuditedEntity<TPrimaryKey, TUser> :與AuditedEntity<TPrimaryKey>的區別就是其支持泛型類型的LastModifierUser和CreatorUser。
IAudited:從其父類接口那繼承了Creation,Modification和delete 的時間和UserID,這個是long類型
FullAuditedEntity<TPrimaryKey> :支持主鍵是泛型類型的Entity,而且從其父類接口那繼承了Creation,Modification和delete 的時間和UserID,這個是long類型
FullAuditedEntity:與FullAuditedEntity<TPrimaryKey>的區別就是其只支持主鍵是int類型的Entity
FullAuditedEntity<TPrimaryKey, TUser> :與FullAuditedEntity<TPrimaryKey>的區別就是其支持泛型類型的LastModifierUser,CreatorUser 和 deleteuser。