问题描述
我的存储库处理丰富的域模型并为其提供持久性。我不想将贫乏的Entity Framework数据实体暴露给我的业务层,因此我需要在它们之间进行映射的方法。
My repositories deal with and provide persistence for a rich domain model. I do not want to expose the anemic, Entity Framework data entity to my business layers, so I need some way of mapping between them.
在大多数情况下,构建域数据实体中的模型实例需要使用参数化的构造函数和方法(因为它很丰富)。它不像属性/字段匹配那么简单。可以将AutoMapper用于相反的情况(映射到数据实体),但不能用于创建域模型。
In most cases, constructing a domain model instance from a data entity requires the use of parameterised constructors and methods (since it is rich). It is not as simple as a property/field match. AutoMapper could be used for the opposite situation (mapping to data entities) but not when creating domain models.
以下是我的存储库模式的核心。
Below is the core of my repository pattern.
EntityFrameworkRepository
类可使用两种通用类型:
The EntityFrameworkRepository
class works with two generic types:
-
TDomainModel
:富域模型 -
TEntityModel
:实体框架数据实体
TDomainModel
: The rich domain modelTEntityModel
: The Entity Framework data entity
定义了两种抽象方法:
-
ToDataEntity(TDomainModel)
:转换为数据实体(用于Add()
和Update()
方法) -
ToDomainModel(TEntityModel)
:构造域模型(用于Find()
方法)。
ToDataEntity(TDomainModel)
: To convert to data entities (forAdd()
andUpdate()
methods)ToDomainModel(TEntityModel)
: To construct domain models (for theFind()
method).
这些方法的具体实现将定义相关存储库所需的映射。
Concrete implementations of these methods would define the mapping required for the repository in question.
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
时急切地从 CompanyRepository
加载它们,那么我在哪里定义部门
和 DepartmentDataEntity
?
A Company
might be composed of many Departments
. If I want to eagerly load these from the CompanyRepository
when fetching a Company
then where would I define the mapping between a Department
and a DepartmentDataEntity
?
我可以提供更多映射 CompanyRepository
中的方法,但这很快就会变得混乱。
I could provide more mapping methods in the CompanyRepository
, but this will soon get messy. There would soon be duplicated mapping methods across the system.
什么是更好的解决上述问题的方法?
What is a better approach to the above problem?
推荐答案
如果您使用Entity Framework,它可以映射Rich Domain Model本身。
If you you use Entity Framework, it can map Rich Domain Model itself.
我已经回答了类似的问题。
I've answered the similar question "Advice on mapping of entities to domain objects" recently.
我一直在使用NHibernate,并且知道在Entity Framework中,您还可以指定从DB表到POCO对象的映射规则。在实体框架实体上开发另一个抽象层是一项额外的工作。让ORM负责所有,状态跟踪,和实现等。现代ORM知道如何处理所有这些问题。
I've been using NHibernate and know that in Entity Framework you can also specify mapping rules from DB tables to your POCO objects. It is an extra effort to develop another abstraction layer over Entity Framework entities. Let the ORM be responsible for all of the mappings, state tracking, unit of work and identity map implementation, etc. Modern ORMs know how to handle all these issues.
您完全正确。
当一个实体可以映射到另一个实体而没有其他依赖项(例如存储库,服务等)时,Automapper很有用。
Automapper is useful when one entity can be mapped into another without additional dependencies (e.g. Repositories, Services, ...).
我将其放入 DepartmentRepository
并添加方法 IList< Department> FindByCompany(int companyId)
以便恢复公司的部门。
I would put it into DepartmentRepository
and add method IList<Department> FindByCompany(int companyId)
in order to retreive company's departments.
有什么更好的方法来解决上述问题?
What is a better approach to the above problem?
如果需要获取另一个实体的部门
的列表,则应将新方法添加到 DepartmentRepository
并仅在需要的地方使用。
If it is needed to get list of Department
s for another entity, a new method should be added to DepartmentRepository
and simply used where it is needed.
这篇关于存储库模式以及域模型与实体框架之间的映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!