Patrón de repositorio y mapeo entre modelos de dominio y Entity Framework

Mis repositorios tratan y proporcionan persistencia para un modelo de dominio enriquecido. No quiero exponer la entidad de datos Entity Framework anémica a mis capas empresariales, por lo que necesito alguna forma de mapeo entre ellas.

En la mayoría de los casos, la construcción de una instancia de modelo de dominio a partir de una entidad de datos requiere el uso de métodos y constructores parametrizados (ya que es rica). No es tan simple como una coincidencia de propiedad / campo. AutoMapper podría usarse para la situación opuesta (mapeo a entidades de datos) pero no al crear modelos de dominio.

A continuación se muestra el núcleo de mi patrón de repositorio.

losEntityFrameworkRepository La clase trabaja con dos tipos genéricos:

TDomainModel: El modelo de dominio ricoTEntityModel: La entidad de datos Entity Framework

Se definen dos métodos abstractos:

ToDataEntity(TDomainModel): Convertir a entidades de datos (paraAdd() yUpdate() métodos)ToDomainModel(TEntityModel): Para construir modelos de dominio (para laFind() método).

Las implementaciones concretas de estos métodos definirían el mapeo requerido para el repositorio en cuestión.

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);
}

Aquí hay un ejemplo básico de una implementación de repositorio:

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
        }
    }
}

Problema:

A Company podría estar compuesto de muchosDepartments. Si quiero cargar con entusiasmo estos desde elCompanyRepository cuando va a buscar unCompany entonces, ¿dónde definiría la asignación entre unaDepartment y unDepartmentDataEntity?

Podría proporcionar más métodos de mapeo en elCompanyRepository, pero esto pronto se ensuciará. Pronto habría duplicados métodos de mapeo en todo el sistema.

¿Cuál es un mejor enfoque para el problema anterior?

Respuestas a la pregunta(6)

Su respuesta a la pregunta