Мои хранилища касаются и обеспечивают постоянство для модели с богатым доменом. Я не хочу раскрывать анонимный объект данных 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
}
}
}
Проблема:
A Company
может состоять из многих Departments
. Если я хочу с нетерпением загрузить их из CompanyRepository
при извлечении Company
, то где бы я определял отображение между a Department
и a DepartmentDataEntity
?
Я мог бы предоставить больше методов сопоставления в CompanyRepository
, но это скоро станет беспорядочным. Скоро будут дублированные методы сопоставления в системе.
Каков наилучший подход к вышеуказанной проблеме?