C# Иерархическая структура и Entity Framework 6
Всем здравствуйте! Пишу простенькую программку для своего производства. C# изучаю довольно недавно и столкнулся с проблемой. Опишу цель и задачи, которые необходимо решить:
Программа на WinForms, доступ к БД MS SQL - Entity Framework 6.0. К примеру, фактически имеется множество деталей: деталь1, деталь2, деталь3 ... деталь150, у всех деталей есть поля:
<деталь1>
- Наименование
- Номер чертежа
- Операция и т.п. Каждая деталь состоит из списка деталей, но каких-то деталей должно быть некоторое кол-во: {деталь3-3шт., деталь15-1шт., деталь45-450шт.} Каждая из этих деталей тоже в свою очередь состоит из каких-то деталей. Как бы казалось, что структура - простая иерархия, но только ровно до того момента, пока детали не пересекаются, например: Есть три детали - деталь1, деталь2 и деталь3:
<деталь1>
- наименование
- №чертежа
- Состав: деталь4-1шт., деталь5-1шт., деталь6-35шт., деталь7-450шт.
<деталь2>
- наименование -№чертежа
- Состав: деталь8-1шт., деталь5-3шт., деталь7-300шт.
Тут как бы нет проблем и всё работает нормально и понятно, объекты сохраняются в БД без проблем. Но если в иерархию вступают ниже приведенная деталь, то нифига не получается:
<деталь3>
- наименование
- №чертежа
- Состав: деталь9-1шт., деталь1-1шт., деталь2-10шт.
И когда я пытаюсь сохранить сие чудо - пишет, что присутствуют множественные ссылки. И не пойму как реализовать структуру.
Теперь к задаче: мне необходимо в БД сохранить шаблон по которому будут создаваться заказы и отслеживаться их выполнение. К примеру: сначала в БД сохраняются шаблоны Деталей с их структурой, затем мне приходит заказ на "Деталь3" - я должен создать объекты по этому шаблону со структурой: <Деталь3>
- Наименование: Деталь №3
- №Чертежа: №1234
- Состав: <Деталь8> {нужно - 1, сделано - 0} <Деталь5> {нужно - 3, сделано - 0} - Наименование - №чертежа - Состав: деталь4 {нужно - 1, сделано - 0} деталь5 {нужно - 1, сделано - 0} .... <Деталь2> {нужно - 10, сделано - 0} - Наименование - №чертежа - Состав: деталь4 {нужно - 1, сделано - 0} деталь5 {нужно - 1, сделано - 0} ....
Далее я изменяю кол-во изготовленных деталей с низа дерева до конечного изготовления детали3. Я уже битый месяц перебираю различные варианты реализации этой задачи, но не могу придумать структуру этих объектов. Если не сложно - помогите хотя бы направить на мысль в каком направлении смотреть..
В идеале - есть множество структур, состоящих из экземпляров класса Р. в каждой структуре есть дочерние экземпляры, в которых есть ещё дочерние и так сколько угодно. Но любой из экземпляров может быть и дочерним элементом совсем другой структуры. Я работаю с EntityFramework 6. В решении всё работает как положено, но при отправке объекта в БД SQL ругается на множественные ссылки, типа на один объект не могут ссылаться несколько объектов. Плюс ко всему каждый объект Р может иметь различные варианты исполнения (прим. Р2).
Ответы (1 шт):
Существует несколько способов хранения иерархий в реляционных СУБД. Здесь описаны четыре основных: Иерархические структуры и деревья в SQL. Кроме того, возможны их комбинации.
У каждого из способов есть достоинства и недостатки. Следует определить, какие операции чаще всего будут нужны в нашем приложении и выбрать наиболее подходящий способ.
Потом нужно прикинуть, а подходит ли этот способ под нашу СУБД? В частности, для работы со списками смежности (adjacency list) необходимо, чтобы СУБД умела делать рекурсивные запросы в CTE. При использовании подмножеств необходимы триггеры для поддержания ссылочной целостности. Бывают некоторые СУБД, которые не имеют то или другое.
Далее смотрим на возможности выбранной СУБД. В некоторых есть встроенные средства для работы с иерархическими структурами. Например, в Sql Server есть тип hierarchyid, а в PostgreSQL есть расширение ltree. Оба являются реализаций матиреализованного пути. Этот способ, возможно, окажется не идеальным именно для нашего случая, но т. к. он встроен в СУБД, то наверняка окажется быстрым и более удобным для использования.
Далее, решаем, с помощью чего будем работать с базой данных. При использовании сырых SQL-запросов нам доступны все возможности. Но если берём ORM, то она ограничивает нас. И сперва следует поискать, может ли эта ORM на выбранной СУБД использовать тот или иной способ работы с иерархиями. Вот, например, нашлась такая статья: Hierarchy in the Entity Framework 6 with the hierarchyid type.