Инкапсуляция ядра EF в шаблоне единицы работы - PullRequest
0 голосов
/ 15 мая 2018

У меня проблемы с подключением DDD и EF Core.

Я делаю проект с использованием архитектуры DDD. В качестве уровня доступа к данным я использую общий шаблон единиц работы, взятый из здесь .

public interface IUnitOfWork
{
    IRepository<TDomain> Repository<TDomain>() where TDomain : class;
}

public interface IRepository<TDomain>
{
    TDomain Get(Expression<Func<TDomain, bool>> predicate);
}

Понимая эти интерфейсы, я использую EF Core.

У меня есть некоторая модель предметной области с 2 классами

public class MainClass
{
    public int Id { get; set; }

    public List<RelatedItem> Items { get; set; }
}

public class RelatedItem
{
    public int Id { get; set; }

    public MainClass Parent { get; set; }

    public DateTime Date { get; set; }

    public string SomeProperty { get; set; }
}

В реальной жизни моего проекта MainClass имеет коллекцию с сотнями RelatedItems. Для выполнения некоторых операций мне нужен только один RelatedItem на запрос с определенной датой. Это можно сделать, выполнив поиск через свойство Items.

Инкапсуляция производительности EF Core в единицу работы. Я должен явно загружать сущности из БД со связанными элементами, потому что уровень входа в систему бизнеса ничего не знает о реализации репозитория UnitOfWork. Но эта операция очень медленная.

Поэтому я решил создать MainClassService, который внедряет в конструктор unitOfWork и имеет метод, который возвращает только один RelatedItem, и он отлично работает.

public class MainClassService
{
    IUnitOfWork unitOfWork;

    public MainClassService(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork ?? throw new ArgumentNullException();
    }

    public RelatedItem GetRelatedItemByDate(int mainClassId, DateTime date)
    {
        return unitOfWork.Repository<RelatedItem>().Get(c => c.Parent.Id == mainClassId && c.Date == date);
    }
}

Итак, у меня есть ситуация, когда я не могу использовать свойство Items напрямую из-за EF Core, но я должен использовать их из-за архитектуры DDD.

И мой вопрос: можно ли использовать такую ​​конструкцию?

1 Ответ

0 голосов
/ 16 мая 2018

Из того, что кажется из вашего вопроса, MainClass является Совокупным корнем, а RelatedItem является вложенной сущностью.Это проектное решение должно основываться на бизнес-правилах / инвариантах, которые должны быть защищены.Когда Aggregate необходимо мутировать, он должен быть полностью загружен из хранилища, то есть корень Aggregate и все его вложенные сущности и объект значения должны находиться в памяти перед выполнением команды мутирования, независимо от того, насколько он велик.

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

Итак, из того, что я написал, вы можете видеть, что проблема проявляется только тогда, когда вы пытаетесь изменить агрегат.Если вам нужно только прочитать или найти его, вы можете создать несколько специализированных служб, которые находят данные с использованием компонентов инфраструктуры.Ваш MainClassService кажется таким случаем, когда вам нужно только прочитать / найти несколько RelatedItem сущностей.

Чтобы было ясно, что целью является только чтение, MainClassService должен возвращать только для чтения представление RelatedItem сущностей.

Итак, вы только что сделали первые шаги к CQRS , где модели разделены на две части: модель READ и модель WRITE.

...