Используя шаблон репозитория, лучше ли сохранять родительские и дочерние объекты вместе или по отдельности? - PullRequest
5 голосов
/ 18 июня 2009

Наличие родительского объекта Сотрудник со списком дочерних объектов Address:

class Employee
{
    List<Address> addresses;
}

и метод репозитория:

void Insert(Employee);

Должен ли код в этом репозитории пытаться сохранить родительский объект Employee, а также дочерние объекты Address или отдельные репозитории должны обрабатывать родительские и дочерние объекты?

Если отдельные репозитории, то при сохранении объекта Employee и его дочерних элементов в клиентском коде это должны быть отдельные вызовы на этом уровне, объединенные в каком-либо сервисе или есть другая альтернатива?

Ответы [ 5 ]

5 голосов
/ 18 июня 2009

Репозиторий должен обрабатывать весь агрегатный объект (родительский и все дочерние), потому что именно это делает его репозиторием. Если вы сохраняете корневые и дочерние объекты по отдельности, то используемый вами шаблон на самом деле не называется репозиторием (хотя, возможно, он все еще будет очень хорошим решением)

«Репозиторий» - это просто удобное имя для конкретного шаблона доступа к данным, который загружает и сохраняет целые агрегаты за один раз - поэтому, когда вы говорите другому разработчику, что вы используете шаблон репозитория, они знают, что это происходит .

1 голос
/ 31 августа 2012

Существует два вида связей между сущностями.

Один равен ссылкой : когда одна сущность содержит ссылку на другую. Эти объекты являются независимыми, и любой из них может быть объединен с другим соответствующим объектом этого типа.

Например: клиент и продукт, пользователь и адрес и т. Д.

Другой тип - это aggreagting : когда несколько объектов представляют один объект, который по некоторым причинам хранится в нескольких таблицах / разбивается на несколько классов. Но это все еще должен быть единственный объект: одна часть не имеет смысла без другой и не может быть объединена с другой сущностью. В этом случае одна сущность всегда мажор , а удаление мажора всегда приводит к удалению агрегированных сущностей.

Например: заказ и заказ предметов, дом и его комнаты и т. Д.

Ссылка представляет отношение, агрегация представляет владение.

SO Сохранение сущности со ссылкой не должно сохранять ссылочную сущность (за исключением случая, когда ссылочная сущность является новой, но в этом случае предпочтительно сохранять ссылочную сущность раньше).

Сохранение объекта с агрегатами должно сохранять агрегированные объекты. В одной транзакции. Потому что это один объект. Также предпочтительно не разрешать сохранение агрегатов по отдельности (только если производительность очень критична), иначе вы столкнетесь с большим количеством проблем с параллелизмом.

0 голосов
/ 18 июня 2009

Я предпочитаю NHibernate, который обрабатывает каскадные сохранения для вас.

0 голосов
/ 18 июня 2009

Я предпочитаю репозиторий для каждой таблицы, но склеиваю их вместе в агрегированный репозиторий:

public RootEmployeeRepository (
  IEmployeeRepository employeeRepository, 
  IAddressRepository addressRepository)
{
  // init
}

public SaveEmployee (Employee employee)
{
  // call IEmployeeRepository to save the employee record minus childen
  // call IAddressRepository to save employee.addresses
  // commit all changes to the DB via UnitOfWork
}
0 голосов
/ 18 июня 2009

Я бы попробовал перейти с шаблоном «Единица работы», где вы открываете, вносите изменения, фиксируете, а затем он просто определяет, что нужно сделать.

Если вы находитесь в реляционной базе данных, вы получите что-то вроде Hibernate с маппером на таблицу. Если вы находитесь в нереляционной базе данных, вам, возможно, придется проявить творческий подход и пометить доменные объекты как IAggregateRoot или что-то еще, чтобы узнать, какие из них имеют свои собственные репозитории, а какие нет.

Например, если сотрудники хранятся в одном SOA, а адреса - в другом, каждый из них будет IAggregateRoots, и в идеале единица работы должна автоматически передавать каждый из грязных экземпляров в соответствующий репозиторий для сохранения.

Таким образом, он прозрачен для клиентского кода, но не является бесполезным слоем косвенности (как это обычно бывает с сервисами в мире java - не всегда, но теми, которые я видел).

Мне нравится DDD, но я думаю, что это завышает репозитории и, эмпирически, вызывает много путаницы, потому что люди всегда спрашивают, как их правильно делать.

Если бы у меня не было системы с несколькими известными бэкэндами на основе SOA (а не просто "эй, мы можем когда-нибудь стать Amazon и нам это нужно"), я бы лично отказался от репозиториев. Конечно, основанные на Hibernate мапперы / DAO / что-то, но они кажутся более простыми и конкретными, чем репозитории.

...