ABP理論學習之實體類


返回總目錄


本篇目錄

實體是DDD(領域驅動設計)的核心概念之一。Eirc Evans是這樣描述的實體的:“它根本上不是通過屬性定義的,而是通過一系列連續性和標識定義的”。因此,實體都有Id屬性並且都存儲到數據庫中。一個實體一般會映射到數據庫的一張表。

實體類###

在ABP中,實體派生自Entity類,看下面的例子:

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;
    }
}

而且,你也可以把它設置為string,Guid或其他類型的。

Entity類重寫了等號運算符(==),可以輕松地檢查兩個實體是否相同了(實體的Id相同則認為它們相同)。它也定義了IsTransient方法來檢測它是否有Id。

慣例接口###

在許多應用中,使用了相似的實體屬性(和數據表中的字段),如CreationTime表明該實體是何時創建的。ABP提供了很多有用的接口來使得這些通用的屬性變得明確並富有表現力。此外,這也為實現了這些接口的實體類提供了一種編寫通用代碼的方式。

審計

IHasCreationTime使得使用一個通用的屬性來描述一個實體的“創建時間”信息成為可能。當實現了該接口的實體類插入到數據庫中時,ABP會自動地將當前的時間設置給CreationTime。

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; }
}

當更新一個實體的時候,ABP也會自動地設置這些屬性。你只需要為你的實體實現這些接口即可。

如果你想實現所有的審計屬性,那么你可以直接實現IAudited接口:

public interface IAudited : ICreationAudited, IModificationAudited
{
        
}

作為一個快捷方式,你可以從AuditedEntity類派生,而不需要直接實現IAudited。AuditedEntity類對於不同類型的Id屬性也有泛型的版本。

軟刪除

軟刪除是將一個實體標記為已刪除的通常使用的模式,而不是直接從數據庫中刪除。比如,你可能不想從數據庫中硬刪除一個User,因為它可能關聯其他的表。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類派生你的實體類從而實現所有的審計接口。

注意:所有的審計接口和類都有一個定義導航屬性到User實體的泛型版本(比如ICreationAudited 和FullAuditedEntity<TPrimaryKey,TUser>)。

激活/未激活

一些實體需要標記為激活的或未激活的。這樣,你就可以根據實體的激活或者未激活狀態來采取行動。你可以實現IPassivable接口來達到目的。該接口定義了IsActive屬性。

如果實體在第一次創建時是激活的,那么你可以在構造函數中將IsActive設置為true。

這與軟刪除(IsDeleted)是不同的。如果一個實體是軟刪除的,那么它就不會從數據庫中檢索到了(ABP默認會阻止),但是,對於激活或者未激活的實體,控制獲取實體完全取決於你。

IEntity接口###

實際上,Entity類實現了IEntity接口(且Entity 實現了IEntity )。如果不想從Entity類中派生,那么可以直接實現這些接口。但是,除非你有一個好的原因不從Entity類派生,否則,不建議這么做。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM