Entity Framework и ООП. Как правильно реализовать принцип согласованности?
В ходе разборок с DDD, возник вопрос который ломает мне мозг.
На примере такой предметной области:
Есть небольшой магазин, в нем необходимо автоматизировать процесс продажи и прием продукции на складе.
У нас существуют три варианта документа с которыми работает магазин: Чек, Возврат от покупателя, Накладная.
Кейсы (берем обычные тривиальные случаи):
1. Продажа: приходит человек, пробивается чек, списывается товар из номенклатуры.
2. Возврат от покупателя: приходит человек, оформляется возврат, товар возвращается на склад.
3. Накладная: приходит товар, оформляется накладная, товар добавляется на склад.
Теперь попробуем разбить на сущности:
1. Если брать со стороны Domain-Driven Design:
Product - товар
Order - чек
OrderLine - позиция в чеке, которая не может существовать без чека и продукта и списывает количество товара на складе
Return - Возврат от покупателя, добавляет количество товара
ReturnLine - позиция в возврате
Consignment - накладная
ConsigmentLine - позиция в накладной, добавляет количество товара
2. Data-Driven Design:
Product - товар
Document - документ, с типом(Чек, Возврат, Накладная)
DocumentLine - позиция документа
Как правильно реализовать связь между Business и Database уровнями? Маппинг?
В случае использования маппинга как решить проблему сохранения, добавления позиций, если используется Entity Framework?
Есть ли возможность подходом Code First реализовать классы из Domain-Driven для работы с базой данных, при чем чтобы таблица была одна?
> Как правильно реализовать связь между Business и Database уровнями? Маппинг?
А для чего вам EF тогда?
> В случае использования маппинга как решить проблему сохранения, добавления позиций, если используется Entity Framework?
Любая нормальная ORM имеет возможность мапать коллекции элементов в том или ином виде. Добавление позиции в коллекцию при правильном маппинге должно приводить к добавлению строк в соответствующую таблицу с нужными значениями внешних ключей.
> при чем чтобы таблица была одна?
насчет одной таблицы вообще не понял. Какая одна таблица?
В базе данных у нас будет три таблицы Documents, DocumentLines, Product
>А для чего вам EF тогда?
Я имел ввиду не маппинг БД и ORM, а маппинг между сущностями Document и Order, DocumentLine и OrderLine.
>Любая нормальная ORM имеет возможность мапать коллекции элементов в том или ином виде. >Добавление позиции в коллекцию при правильном маппинге должно приводить к добавлению строк >в соответствующую таблицу с нужными значениями внешних ключей.
Безусловно, но если мы напрямую работаем с сущностью Document, но не Order.
> при чем чтобы таблица была одна?
Таблица Documents -> это абстракция для Order, Consignment, Return. То есть сериализация и материлизация на лету. Но этот вопрос я выяснил, Repository в любом случае должен передавать коллекцию объектов одного типа.
Pavel_Develop
> Я имел ввиду не маппинг БД и ORM, а маппинг между сущностями Document и Order
что-то совсем непонятно стало. Для маппинга саб-классов на таблицы есть несколько стратегий: single-table inheritance, class-table inheritance concrete table inheritance, single table замапает вам несколько классов на одну таблицу. Это конечно если вы пришли к тому, что вам действительно нужно несколько классов.
Спасибо очень полезные ссылки, как раз я имел ввиду single table inheritance, в контекте вопроса про одну таблицу много классов.
Насчет маппинга имелось ввиду маппинг в самом проекте пример здесь: cpratt.co/using-automapper-getting-started
Pavel_Develop
не пользуюсь, это антипаттерн и я вполне обхожусь без него (т.е. помещаю логику в модельные классы). Он появляется от чрезмерного желания разделить приложение на много слоев, отчего некоторые слои в конце-концов мало что толкового делают (пресловутые Business Logic layer и Data Layer).
Что удалось нарыть:
Работают непосредственно с сущностями, которые генерит ORM с помощью Repository. А вся бизнес-логика располагается в Service. Делают маппинг с помощью AutoMapper с использованием ViewModel на стороне Presentation. Бывает Service и Repository дробят на мелкие классы Query и Command.