【发布时间】:2014-01-23 13:20:19
【问题描述】:
我的存储库处理并为富域模型提供持久性。我不想将贫血的 Entity Framework 数据实体暴露给我的业务层,因此我需要某种方式在它们之间进行映射。
在大多数情况下,从数据实体构造域模型实例需要使用参数化的构造函数和方法(因为它很丰富)。它不像属性/字段匹配那么简单。 AutoMapper 可用于相反的情况(映射到数据实体),但不能用于创建领域模型。
以下是我的存储库模式的核心。
EntityFrameworkRepository 类适用于两种泛型类型:
-
TDomainModel:富域模型 -
TEntityModel: Entity Framework 数据实体
定义了两个抽象方法:
-
ToDataEntity(TDomainModel):转换为数据实体(用于Add()和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
}
}
}
问题:
一个Company 可能由许多Departments 组成。如果我想在获取Company 时从CompanyRepository 急切地加载这些,那么我将在哪里定义Department 和DepartmentDataEntity 之间的映射?
我可以在CompanyRepository 中提供更多映射方法,但这很快就会变得混乱。很快就会在整个系统中出现重复的映射方法。
解决上述问题的更好方法是什么?
【问题讨论】:
-
1.严格按照经营理念定义公司。 2. 为实体用例建模 3. 请注意,如果做得正确,您将不会遇到现在遇到的问题。并忽略与持久性相关的任何内容
-
AutoMapper 可以用于相反的情况[...],但在创建域模型时却不行。 为什么不可能both 方式?
-
@ThomasWeller,AutoMapper 的创建者 Jimmmy Bogard 给出了答案 - The case for two-way mapping in AutoMapper。
-
@davenewza,您是决定使用问题中描述的方法还是直接映射到域模型?
标签: .net entity-framework domain-driven-design repository-pattern onion-architecture