簡體   English   中英

從域模型繼承持久性模型以節省使用實體框架的映射工作有哪些缺點?

[英]What are the disadvantages to inheriting Persistence Models from Domain Models to save mapping effort using Entity Framework?

我一直在考慮從原始域模型(DM)類繼承我的持久性模型(PM),以便添加一些對持久性邏輯很重要的屬性。 這樣,我將不必處理很多映射代碼。

為了簡單起見,這里是一個表示信用的DM,用戶或組織可以用來下訂單。

namespace Foo.Domain
{
    // Domain Model
    public class Credit : IDomainEntity, IAggregateRoot
    {
        public Credit(int? userId, int? organizationId, DateTime expiryDate)
        {
            if(userId == null && organizationId == null)
                throw new InvalidOperationException("MUST assign credit to user OR organization.");
            if(userId != null && organizationId != null)
                throw new InvalidOperationException("CANNOT assign credit to user AND organization.");

            UserId = userId;
            OrganizationId = organizationId;
            ExpiryDate = expiryDate;
        }

        public virtual int Id { get; private set; }
        public virtual DateTime ExpiryDate { get; private set; }

        // external IAggregateRoot objects are linked by reference
        public virtual int? UserId { get; private set; }
        public virtual int? OrganizationId { get; private set; }
        public virtual int? OrderId { get; private set; }

        public void AttachToOrder(int orderId)
        {
            if (ExpiryDate >= DateTime.UtcNow)
                throw new InvalidOperationException("Credit is expired.");
            if (OrderId != null)
                throw new InvalidOperationException("Credit is unavailable.");

            OrderId = orderId;
        }

        public void DetachFromOrder()
        {
            if (OrderId == null)
                throw new InvalidOperationException("Credit is available.");

            OrderId = null;
        }
    }
}

假設我要在外鍵約束下保持該模型。 實體框架Fluent API需要導航屬性才能執行此操作。 因此,我無法直接持久化域模型也無法從關系數據庫中的外鍵約束檢查中受益。

我的想法是繼承PM以添加所需的導航屬性。 由於EF也需要無參數的構造函數,因此很遺憾,我將不得不將其添加到DM中,盡管幸運的是,它不會對其不變量產生影響。

namespace Foo.Domain
{
    // Adjusted Domain Model
    public class Credit : IDomainEntity, IAggregateRoot
    {
        protected Credit() { }

        public Credit(int? userId, int? organizationId, DateTime expiryDate)
            : this()

        // remainder of the class unchanged
    }
}

namespace Foo.Infrastructure
{
    // Persistence Model
    public class Credit : Foo.Domain.Credit
    {
        protected Credit()
            : base()
        {
        }

        public Credit(int? userId, int? organizationId, DateTime expiryDate)
            : base(userId, organizationId, expiryDate)
        {
        }

        public virtual User User { get; private set; }
        public virtual Organization Organization { get; private set; }
        public virtual Order Order { get; private set; }
    }
}

現在,我假設可以在Fluent API中像這樣使用它:

modelBuilder.Entity<Credit>()
    .HasOptional<Order>(c => c.Order) // this is why I need the navigation property
    .WithMany()
    .HasForeignKey(c => c.OrderId);

..並像這樣定義我的DbContext:

namespace Foo.Infrastructure
{
    public interface IFooDbContext
    {
        IDbSet<Credit> Credits { get; }

        Task<int> SaveChangesAsync();
    }
}

您對這種方法有何看法?

對我而言,主要缺點是從域實體轉換為持久性實體。 當從存儲庫獲取數據時-可以,只需將Foo.Infrastructure.CreditFoo.Domain.Credit即可(沒有繼承)。 但是,當您需要保存新的Foo.Domain.Credit ,必須創建新的對象Foo.Infrastructure.Credit並將屬性從第一到第二進行映射。 因此,您不能只調用new Foo.Domain.Credit ,您需要使用一個工廠,而該工廠必須了解Foo.Infrastructure.Credit ,這看起來並不好。 不幸的是,實體框架不允許我們將域實體設計為“純”的,而持久性卻是無知的,因此我們必須對其進行處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM