DDD репозитории с явной загрузкой EF - PullRequest
0 голосов
/ 17 мая 2019

Я начинаю разбираться в Domain Driven Design, и у меня возникают некоторые проблемы с репозиториями, и тот факт, что EF Core явно загружает, автоматически заполнит мои навигационные свойства.

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

Пример:

  1. Загрузка владельцев расписаний

  2. Рассчитать диапазон дат

  3. Загрузить расписание владельца расписания

Я пытаюсь сохранитьмой уровень доступа к данным изолирован от основного уровня, и здесь у меня есть несколько вопросов.

Представьте себе этот метод в моем хранилище:

public List<Schedule> GetSchedules(Guid scheduleOwnePk, DateRange dateRange)
{
   var schedules = dbContext.Schedules.Where(x => x.PkScheduleOwner == scheduleOwnerPk && x.StartDate >= dateRange.Start && x.EndDate <= dateRange.End).ToList();
   return schedules;
}

Я могу вызвать этот метод из основного уровня вдвумя способами:

//Take advantage of EF core ability to fill the navigational property automatically 
scheduleOwnerRepository.GetSchedules(scheduleOwner.Pk, dateRange)

или

var schedules = scheduleOwnerRepository.GetSchedules(scheduleOwner.Pk, dateRange);
//At this moment EF core already loaded the navigational property, so I need to clear it to avoid duplicated results
scheduleOwner.Schedules.Clear();
//Schedules is implemented as an IEnumerable to protect it from being changed outside the aggregator root
scheduleOwner.AddSchedules(schedules);

Проблема с первым подходом состоит в том, что он пропускает ядро ​​EF в слой ядра, что означает, что свойство ScheduleOwner.Schedules больше не будетзаполнен, если я отойду от ядра EF.

Второй подход абстрагирует ядро ​​EF, но требует некоторых дополнительных шагов, чтобы заполнить ScheduleOwner.Schedules.Так как ядро ​​EF автоматически загрузит навигационное свойство после вызова метода репозитория, я вынужден очистить его перед добавлением результатов, в противном случае я буду вставлять дублированные результаты.

Как вы, ребята, справляетесь с этимтакая ситуация?Используете ли вы основные функции EF или используете более естественный подход вызова метода репозитория и используете его результаты для заполнения какого-либо свойства?

Спасибо за помощь.

1 Ответ

3 голосов
/ 17 мая 2019

Здесь необходимо учесть несколько моментов.

Старайтесь избегать использования модели вашего домена для запросов.Скорее используйте модель чтения через слой запроса .

Агрегат - это целая единица, как и при загрузке, вы загружаете все.Когда вы сталкиваетесь со сценарием, в котором вам не нужны все связанные данные, это может указывать на то, что данные не являются частью совокупности, но на самом деле они могут быть связаны только в более слабом смысле.

Примером является Order до Customer.Хотя для Order вполне может потребоваться Customer, Order сам по себе является совокупностью.Customer может иметь список OrderIds, но он может стать довольно большим.Обычно не требуется полный список заказов, чтобы определить, является ли агрегат действительным или полным.Тем не менее, вам вполне может понадобиться список ActiveOrder объектов сорта значений, если это требуется, скажем, для сохранения максимальной суммы заказа, хотя есть и другие способы решения этого вопроса.

Назад кваш сценарийСущность EF не является моделью вашего домена, и когда в прошлом мне приходилось использовать EF, я загружал эту сущность, а затем отображал ее на свою сущность домена в хранилище.Репозиторий будет работать только с агрегатами домена, и вам следует избегать методов запросов в репозитории.Как минимум, хранилище обычно имеет как минимум метод Get(id) и Save(aggregate).

Я бы рекомендовал использовать отдельный слой, который возвращает максимально простой результат.Для чего-то вроде Count я могу вернуть int, тогда как для чего-то вроде IScheduleQuery.Search(specification) я могу вернуть IEnumerable<DataRow> или, если он содержит более сложные данные или мне нужна модель чтения, я могу вернуть IEnumerable<Query.Schedule>.

...