ABP(現代ASP.NET樣板開發框架)系列之十、ABP領域層——實體

點這裏進入ABP系列文章總目錄html

 

基於DDD的現代ASP.NET開發框架--ABP系列之十、ABP領域層——實體
git

 

ABP是「ASP.NET Boilerplate Project (ASP.NET樣板項目)」的簡稱。github

ABP的官方網站http://www.aspnetboilerplate.com數據庫

ABP在Github上的開源項目https://github.com/aspnetboilerplate架構

 


本文由深圳-Carl提供翻譯框架

實體是DDD(領域驅動設計)的核心概念之一。Eric Evans是這樣描述的「不少對象不是經過它們的屬性定義的,而是經過一連串的連續性事件和標識定義的」(引用領域驅動設計一書)。函數

譯者注:對象不是經過它們的屬性來下根本性的定義,而應該是經過它的線性連續性和標識性定義的。。因此,實體是具備惟一標識的ID且存儲在數據庫中。實體一般被映射成數據庫中的一個表。網站

實體類(Entity classes) 

在ABP中,實體繼承自Entity類,請看下面示例:ui

public class Person : Entity
{
    public virtual string Name { get; set; }

    public virtual DateTime CreationTime { get; set; }

    public Task()
    {
        CreationTime = DateTime.Now;
    }
}

Person 類被定義爲一個實體。它具備兩個屬性,它的父類中有Id屬性。Id是該實體的主鍵。因此,Id是全部繼承自Entity類的實體的主鍵(全部實體的主鍵都是Id字段)。編碼

Id(主鍵)數據類型能夠被更改。默認是int(int32)類型。若是你想給Id定義其它類型,你應該像下面示例同樣來聲明Id的類型。

public class Person : Entity<long>
{
    public virtual string Name { get; set; }

    public virtual DateTime CreationTime { get; set; }

    public Task()
    {
        CreationTime = DateTime.Now;
    }
}

你能夠設置爲string,Guid或者其它數據類型。

實體類重寫了 equality (==) 操做符用來判斷兩個實體對象是否相等(兩個實體的Id是否相等)。還定義了一個IsTransient()方法來檢測實體是否有Id屬性。

接口約定

在不少應用程序中,不少實體具備像CreationTime的屬性(數據庫表也有該字段)用來指示該實體是何時被建立的。APB提供了一些有用的接口來實現這些相似的功能。也就是說,爲這些實現了這些接口的實體,提供了一個通用的編碼方式(通俗的說只要實現指定的接口就能實現指定的功能)。

(1)審計(Auditing)

實體類實現 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 Task()
    {
        CreationTime = DateTime.Now;
    }
}

ICreationAudited 擴展自 IHasCreationTime 而且該接口具備屬性 CreatorUserId :

public interface ICreationAudited : IHasCreationTime
{
    long? CreatorUserId { get; set; }
}

當保存一個新的實體時,ABP會自動設置CreatorUserId 的屬性值爲當前用戶的Id

你能夠輕鬆的實現ICreationAudited接口,經過派生自實體類 CreationAuditedEntity (由於該類已經實現了ICreationAudited接口,咱們能夠直接繼承CreationAuditedEntity 類就實現了上述功能)。它有一個實現不一樣ID數據類型的泛型版本(默認是int),能夠爲ID(Entity類中的ID)賦予不一樣的數據類型。
下面是一個爲實現相似修改功能的接口

public interface IModificationAudited
{
    DateTime? LastModificationTime { get; set; }
    long? LastModifierUserId { get; set; }
}

當更新一個實體時,APB會自動設置這些屬性的值。你只須要在你的實體類裏面實現這些屬性。

若是你想實現全部的審計屬性,你能夠直接擴展 IAudited 接口;示例以下:

public interface IAudited : ICreationAudited, IModificationAudited
{
        
}

做爲一個快速開發方式,你能夠直接派生自AuditedEntity 類,不須要再去實現IAudited接口(AuditedEntity 類已經實現了該功能,直接繼承該類就能夠實現上述功能),AuditedEntity 類有一個實現不一樣ID數據類型的泛型版本(默認是int),能夠爲ID(Entity類中的ID)賦予不一樣的數據類型。

(2)軟刪除(Soft delete)

軟刪除是一個通用的模式被用來標記一個已經被刪除的實體,而不是實際從數據庫中刪除記錄。例如:你可能不想從數據庫中硬刪除一條用戶記錄,由於它被許多其它的表所關聯。爲了實現軟刪除的目的咱們能夠實現該接口 ISoftDelete:

public interface ISoftDelete{
    bool IsDeleted { get; set; }
}

ABP實現了開箱即用的軟刪除模式。當一個實現了軟刪除的實體正在被被刪除,ABP會察覺到這個動做,而且阻止其刪除,設置IsDeleted 屬性值爲true而且更新數據庫中的實體。也就是說,被軟刪除的記錄不能夠從數據庫中檢索出,ABP會爲咱們自動過濾軟刪除的記錄。(例如:Select查詢,這裏指經過ABP查詢,不是經過數據庫中的查詢分析器查詢。)

若是你用了軟刪除,你有可能也想實現這個功能,就是記錄誰刪除了這個實體。要實現該功能你能夠實現IDeletionAudited 接口,請看下面示例:

public interface IDeletionAudited : ISoftDelete
{
    long? DeleterUserId { get; set; }
    DateTime? DeletionTime { get; set; }
}

正如你所看到的IDeletionAudited 擴展自 ISoftDelete接口。當一個實體被刪除的時候ABP會自動的爲這些屬性設置值。
若是你想爲實體類擴展全部的審計接口(例如:建立(creation),修改(modification)和刪除(deletion)),你能夠直接實現IFullAudited接口,由於該接口已經繼承了這些接口,請看下面示例:

public interface IFullAudited : IAudited, IDeletionAudited
{
        
}

做爲一個快捷方式,你能夠直接從FullAuditedEntity 類派生你的實體類,由於該類已經實現了IFullAudited接口。

注意:全部的審計接口和類都有一個泛型模板爲了導航定義屬性到你的User 實體(例如:ICreationAudited<TUser>和FullAuditedEntity<TPrimaryKey, TUser>),這裏的TUser指的進行建立,修改和刪除的用戶的實體類的類型,詳細請看源代碼(Abp.Domain.Entities.Auditing空間下的FullAuditedEntity<TPrimaryKey, TUser>類),TprimaryKey 只的是Entity基類Id類型,默認是int。

(3)激活狀態/閒置狀態(Active/Passive)

有些實體須要被標記爲激活狀態或者閒置狀態。那麼你能夠爲實體採起active/passive狀態的行動。基於這個緣由而建立的實體,你能夠擴展IPassivable 接口來實現該功能。該接口定義了IsActive 的屬性。

若是你首次建立的實體被標記爲激活狀態,你能夠在構造函數設置IsActive屬性值爲true。

這是不一樣於軟刪除(IsDeleted)。若是實體被軟刪除,它不能從數據庫中被檢索到(ABP已通過濾了軟刪除記錄)。可是對於激活狀態/閒置狀態的實體,你徹底取決於你怎樣去獲取這些被標記了的實體。

IEntity接口

事實上Entity 實現了IEntity 接口(和Entity<TPrimaryKey> 實現了 IEntity<TPrimaryKey>接口)。若是你不想從Entity 類派生,你能直接的實現這些接口。其餘實體類也能夠實現相應的接口。可是不建議你用這種方式。除非你有一個很好的理由不從Entity 類派生。

 


 

但願更多國內的架構師能關注到ABP這個項目,也許這其中有能幫助到您的地方,也許有您的參與,這個項目能夠發展得更好。

歡迎加ABP架構設計交流QQ羣:134710707

ABP架構設計交流羣

 

點這裏進入ABP系列文章總目錄

相關文章
相關標籤/搜索