Wzorzec repozytorium i mapowanie między modelami domeny a ramą Entity Framework

Moje repozytoria radzą sobie i zapewniają trwałość dla modelu bogatej domeny. Nie chcę ujawniać anemicznej, encji Framework jednostki danych do moich warstw biznesowych, więc potrzebuję jakiegoś sposobu mapowania między nimi.

W większości przypadków skonstruowanie instancji modelu domeny z jednostki danych wymaga użycia sparametryzowanych konstruktorów i metod (ponieważ jest bogata). To nie jest tak proste, jak dopasowanie własności / pola. AutoMapper może być użyty w sytuacji odwrotnej (mapowanie do jednostek danych), ale nie podczas tworzenia modeli domeny.

Poniżej znajduje się rdzeń mojego wzorca repozytorium.

TheEntityFrameworkRepository klasa działa z dwoma rodzajami rodzajowymi:

TDomainModel: Model bogatej domenyTEntityModel: Jednostka danych Entity Framework

Zdefiniowano dwie abstrakcyjne metody:

ToDataEntity(TDomainModel): Aby przekonwertować na jednostki danych (dlaAdd() iUpdate() metody)ToDomainModel(TEntityModel): Aby skonstruować modele domen (dlaFind() metoda).

Konkretne implementacje tych metod definiują mapowanie wymagane dla danego repozytorium.

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

Oto podstawowy przykład implementacji repozytorium:

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

Problem:

A Company może składać się z wieluDepartments. Jeśli chcę chętnie załadować te zCompanyRepository przy pobieraniu aCompany to gdzie zdefiniowałbym mapowanie między aDepartment i aDepartmentDataEntity?

Mogę podać więcej metod mapowania wCompanyRepository, ale wkrótce stanie się bałagan. Wkrótce w systemie powielone zostaną metody mapowania.

Jakie jest lepsze podejście do powyższego problemu?

questionAnswers(6)

yourAnswerToTheQuestion