Dot-Net

領域模型和實體框架之間的儲存庫模式和映射

  • January 6, 2014

我的儲存庫處理並為富域模型提供持久性。我不想將貧血的實體框架數據實體暴露給我的業務層,因此我需要某種方式在它們之間進行映射。

在大多數情況下,從數據實體構造域模型實例需要使用參數化的建構子和方法(因為它很豐富)。它不像屬性/欄位匹配那麼簡單。AutoMapper 可用於相反的情況(映射到數據實體),但不能用於創建域模型。

下面是我的儲存庫模式的核心。

該類EntityFrameworkRepository適用於兩種通用類型:

  • TDomainModel: 富域模型
  • TEntityModel: Entity Framework 數據實體

定義了兩個抽象方法:

  • ToDataEntity(TDomainModel): 轉換為數據實體(forAdd()Update()方法)
  • ToDomainModel(TEntityModel):建構領域模型(用於Find()方法)。

這些方法的具體實現將定義相關儲存庫所需的映射。

public interface IRepository<T> where T : DomainModel
{
   T Find(int id);
   void Add(T item);
   void Update(T item);
}

public abstract class EntityFrameworkRepository<TDomainModel, TEntityModel> : IRepository<TDomainModel>
   where TDomainModel : DomainModel
   where TEntityModel : EntityModel
{
   public EntityFrameworkRepository(IUnitOfWork unitOfWork)
   {
       // ...
   }

   public virtual TDomainModel Find(int id)
   {
       var entity = context.Set<TEntityModel>().Find(id);

       return ToDomainModel(entity);
   }

   public virtual void Add(TDomainModel item)
   {
       context.Set<TEntityModel>().Add(ToDataEntity(item));
   }

   public virtual void Update(TDomainModel item)
   {
       var entity = ToDataEntity(item);

       DbEntityEntry dbEntityEntry = context.Entry<TEntityModel>(entity);

       if (dbEntityEntry.State == EntityState.Detached)
       {
           context.Set<TEntityModel>().Attach(entity);

           dbEntityEntry.State = EntityState.Modified;
       }
   }

   protected abstract TEntityModel ToDataEntity(TDomainModel domainModel);
   protected abstract TDomainModel ToDomainModel(TEntityModel dataEntity);
}

這是儲存庫實現的基本範例:

public interface ICompanyRepository : IRepository<Company>
{
   // Any specific methods could be included here
}

public class CompanyRepository : EntityFrameworkRepository<Company, CompanyTableEntity>, ICompanyRepository
{
   protected CompanyTableEntity ToDataEntity(Company domainModel)
   {
       return new CompanyTable()
       {
           Name = domainModel.Name,
           City = domainModel.City
           IsActive = domainModel.IsActive
       };
   }

   protected Company ToDomainModel(CompanyTableEntity dataEntity) 
   {
       return new Company(dataEntity.Name, dataEntity.IsActive)
       {
           City = dataEntity.City
       }
   }
}

問題:

ACompany可能由許多Departments. 如果我想CompanyRepository在獲取 a 時急切地載入這些,Company那麼我將在哪裡定義 aDepartment和 a之間的映射DepartmentDataEntity

我可以在 中提供更多映射方法CompanyRepository,但這很快就會變得混亂。很快就會在整個系統中出現重複的映射方法。

解決上述問題的更好方法是什麼?

我的儲存庫處理並為富域模型提供持久性。我不想將貧血的實體框架數據實體暴露給我的業務層,因此我需要某種方式在它們之間進行映射。

如果您使用實體框架,它可以映射富域模型本身。

我最近回答了類似的問題“關於將實體映射到域對象的建議”

我一直在使用 NHibernate,並且知道在 Entity Framework 中,您還可以指定從 DB 表到 POCO 對象的映射規則。在實體框架實體之上開發另一個抽象層是一項額外的工作。讓 ORM 負責所有的映射、狀態跟踪、工作單元身份映射實現等。現代 ORM 知道如何處理所有這些問題。

AutoMapper 可用於相反的情況(映射到數據實體),但不能用於創建域模型。

你是完全正確的。

當一個實體可以映射到另一個實體而不需要額外的依賴項(例如儲存庫、服務……)時,Automapper 很有用。

…我將在哪裡定義 aDepartment和 a之間的映射DepartmentDataEntity

我會將其放入DepartmentRepository並添加方法IList<Department> FindByCompany(int companyId)以檢索公司的部門。

我可以在 中提供更多映射方法CompanyRepository,但這很快就會變得混亂。很快就會在整個系統中出現重複的映射方法。

解決上述問題的更好方法是什麼?

如果需要獲取Department另一個實體的 s 列表,則應添加一個新方法,DepartmentRepository並在需要的地方簡單地使用它。

引用自:https://stackoverflow.com/questions/20944865