領域模型和實體框架之間的儲存庫模式和映射
我的儲存庫處理並為富域模型提供持久性。我不想將貧血的實體框架數據實體暴露給我的業務層,因此我需要某種方式在它們之間進行映射。
在大多數情況下,從數據實體構造域模型實例需要使用參數化的建構子和方法(因為它很豐富)。它不像屬性/欄位匹配那麼簡單。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 } } }問題:
A
Company可能由許多Departments. 如果我想CompanyRepository在獲取 a 時急切地載入這些,Company那麼我將在哪裡定義 aDepartment和 a之間的映射DepartmentDataEntity?我可以在 中提供更多映射方法
CompanyRepository,但這很快就會變得混亂。很快就會在整個系統中出現重複的映射方法。解決上述問題的更好方法是什麼?
我的儲存庫處理並為富域模型提供持久性。我不想將貧血的實體框架數據實體暴露給我的業務層,因此我需要某種方式在它們之間進行映射。
如果您使用實體框架,它可以映射富域模型本身。
我最近回答了類似的問題“關於將實體映射到域對象的建議”。
我一直在使用 NHibernate,並且知道在 Entity Framework 中,您還可以指定從 DB 表到 POCO 對象的映射規則。在實體框架實體之上開發另一個抽象層是一項額外的工作。讓 ORM 負責所有的映射、狀態跟踪、工作單元和身份映射實現等。現代 ORM 知道如何處理所有這些問題。
AutoMapper 可用於相反的情況(映射到數據實體),但不能用於創建域模型。
你是完全正確的。
當一個實體可以映射到另一個實體而不需要額外的依賴項(例如儲存庫、服務……)時,Automapper 很有用。
…我將在哪裡定義 a
Department和 a之間的映射DepartmentDataEntity?我會將其放入
DepartmentRepository並添加方法IList<Department> FindByCompany(int companyId)以檢索公司的部門。我可以在 中提供更多映射方法
CompanyRepository,但這很快就會變得混亂。很快就會在整個系統中出現重複的映射方法。解決上述問題的更好方法是什麼?
如果需要獲取
Department另一個實體的 s 列表,則應添加一個新方法,DepartmentRepository並在需要的地方簡單地使用它。