Хорошо, это всего лишь предварительный ответ, основанный на множестве чтений повсюду.
public class InvoiceQuery
{
public AppDbContext AppDbContext { get; private set; }
public int Id { get; set; }
public Invoice Execute()
{
return AppDbContext
.Invoices
.Include(nameof(Invoice.InvoiceRows))
.Where(invoice => invoice.Id == Id)
.FirstOrDefault();
}
}
Моя проблема заключалась в том, что это не сильно отличается от того, что у нас было бы в репозитории . Это с практической точки зрения; с теоретической точки зрения, это дает вам правильную точку зрения, в то время как репозиторий вводит в заблуждение. Причина, по которой это вводит в заблуждение, заключается в том, что между сущностями и действиями или запросами, которые вы можете выполнять в базе данных, нет ассоциации 1-1. Даже в этом случае Invoice - это не просто счет-фактура, а Invoice plus InvoiceRows. (Кстати, я думаю, что InvoiceQuery - хорошее имя (а не InvoiceWithRowsQuery), потому что с точки зрения бизнес-логики c счет-фактура - это полностью загруженный счет-фактура; счет-фактура с 0 строками - это пустой счет-фактура, а не частично загруженный счет.)
Таким образом, запрос фокусируется на том, что вы получаете, а не на сущности, с которой вы начинаете, потому что их может быть более одного. Это имя «запроса» является своего рода нелогичным, потому что можно сказать, что по мере продвижения к бизнес-логике c вы перестаете видеть такие вещи, как запросы, и начинаете видеть такие вещи, как параметры. И на самом деле у нас есть параметры, «запрос» - это всего лишь имя контейнера. Возможно, нам следует называть это запросом бизнес-объекта, но это будет слишком долго, но в этом смысл. Таким образом, этот объект запроса представляет собой простой контейнер для запроса EF; Я расскажу об этом позже. В этой реализации на основе классов, помимо того, что она прославляется как объект, нет никаких дополнительных функций. Возможно, вы ожидаете дополнительных функций, вместо этого у вас есть что-то меньшее. Отсутствует то, что они больше не связаны с сущностью. Это еще один противоречащий интуиции факт, который доказывает, что здесь мы что-то разбираем: надуманное представление сущности-репозитория.
Наличие такого простого объекта ставит вопрос. Почему не метод какого-нибудь родственного класса? Если мы поместим его в Entity, мы go вернемся к организации, подобной репозиторию, что кажется некорректным в основном потому, что отсутствующий 1-1 bla bla означает, что во многих случаях вы не можете сказать, с какой сущностью связан запрос. Но некоторые авторы используют своего рода «контейнерный класс», который на самом деле является не более чем контейнером, просто не имеющим права на объект (например, OrdersData). Если я вам нравлюсь, как уроки, у которых есть четкая цель, это вызывает у вас дрожь по спине. Мы начали говорить, что у нас есть решение лучше, чем репозиторий. Что у репозитория так много проблем. В итоге мы получаем класс, в названии которого есть «Данные». Как может лучшее решение быть таким неубедительным? Похоже, что альтернатива репозиторию - это просто куча вещей, а не стабильная и хорошо спроектированная, как ожидалось. С другой стороны, это всего лишь способ сбора запросов (те же запросы, которые были бы у вас в репозитории, очень тот же запрос, который у вас был бы в шаблоне запроса / команды ...) под имя, отличное от имени сущности. Да, похоже, все это сводится к выбору наименования. Сторонники модели репозитория и сторонники запрета на репозиторий яростно борются друг с другом. Затем вы смотрите на код, что он на самом деле делает. Код тот же, и мы говорим только об именах. То есть: если вы посмотрите, что репозитории делают в своих репозиториях, а нерепозитории делают в своих любых (не всегда ясных) классах, они делают то же самое. Но это всего лишь впечатление, я должен это проверить.
В модели репозитория наличие репозитория для объекта с его методами было обнадеживающим. Он предоставил своего рода основу для размещения всех методов. К сожалению, эти леса кажутся слишком ограничивающими, опять же из-за отношения не 1-1 между сущностями и запросами / командами. Тем не менее, мы должны сказать, что объекты root, такие как Invoice (в DDD разговоре Invoice - это root, InvoiceRows являются агрегированными), вполне подходят для организации в стиле репозитория. По этой причине в этом решении, основанном на запросах, плоскостность коллекции запросов не полностью удовлетворяет, и это еще одна причина, по которой я думаю, что хочу более подробно остановиться на этом топе c.