存储库模式以及域模型与实体框架之间的映射 [英] Repository pattern and mapping between domain models and Entity Framework

查看:92
本文介绍了存储库模式以及域模型与实体框架之间的映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的存储库处理丰富的域模型并为其提供持久性。我不想将贫乏的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 model
  • TEntityModel: The Entity Framework data entity

定义了两种抽象方法:


  • ToDataEntity(TDomainModel):转换为数据实体(用于 Add() Update()方法)

  • ToDomainModel(TEntityModel) :构造域模型(用于 Find()方法)。

  • ToDataEntity(TDomainModel): To convert to data entities (for Add() and Update() methods)
  • ToDomainModel(TEntityModel): To construct domain models (for the Find() 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数据实体暴露给我的业务层,因此我需要在它们之间进行某种映射。

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.

如果您使用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 could be used for the opposite situation (mapping to data entities) but not when creating domain models.

您完全正确。

当一个实体可以映射到另一个实体而没有其他依赖项(例如存储库,服务等)时,Automapper很有用。

Automapper is useful when one entity can be mapped into another without additional dependencies (e.g. Repositories, Services, ...).


...在哪里定义部门 DepartmentDataEntity

我将其放入 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.


我可以在 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?

如果需要获取另一个实体的部门的列表,则应将新方法添加到 DepartmentRepository 并仅在需要的地方使用。

If it is needed to get list of Departments for another entity, a new method should be added to DepartmentRepository and simply used where it is needed.

这篇关于存储库模式以及域模型与实体框架之间的映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆