0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
1 | |
EF и коллекции15.03.2017, 17:04. Показов 2054. Ответов 23
Метки нет (Все метки)
Есть класс модели, где одно поле представляет собой коллекцию enum. В БД есть соответствующие таблицы, но там это сделано путем создания дополнительной таблицы. То есть допустим есть класс Item, есть enum Property. У класса Item есть поле List<Property>. В БД есть таблицы items, propeties и set_propety, в которой полю item_id соответствует property_id (ну и может быть несколько строк с одним и тем же item_id, если в коллекции несколько элементов)
Мне в данный момент редактировать БД не надо, просто прочитать бы, чтобы вывести список Property в представление для нужного Item. Подскажите примерно в каком направлении копать. Поможет ли LINQ, надо ли (и возможно ли это в EF) использовать sql-запрос? Или вообще ничего не получится? Пока единственное, что приходит в голову - создать классы моделей, соответствующие таблицам, но класс SetProperty как-то некрасиво в C# будет выглядеть.
0
|
15.03.2017, 17:04 | |
Ответы с готовыми решениями:
23
Получение новой коллекции путем фильтрации элементов коллекции находящихся в другой коллекции Удаление элемента коллекции в коллекции коллекции ) Сделать сортировку коллекции вместо создания новой коллекции с передачей IOrderedEnumerable<T> Как удалить элемент из коллекции, во время перебора этой коллекции foreach? |
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,705
|
|
15.03.2017, 17:53 | 2 |
Посмотрел бы я в глаза тому, кто так называл таблицу.
Если бы это был Code First, то доступ к коллекциям был бы тривиален - через NavigationProperty на вашу коллекцию. Если один enum может включать в себя множество значений, то я бы вообще перепроектировал бд, сделав этот enum обычным свойством и повесив на него атрибут Flags. Создайте класс c любым адекватным именем, и через TableAttribute, либо через Fluent API отображайте на нужную таблицу. Добавлено через 8 минут ps: И с существующей таблицей доступ к связанной коллекции реализуется через NavigationProperty.
1
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
15.03.2017, 18:30 [ТС] | 3 |
IamRain, таблицу так никто не называл, это я тут написал, что в голову пришло. Класса Item тоже нет, он назван по предмету, который описывает, но на вопрос это не влияет, поэтому пишу Item, чтобы не грузить лишней инфой.
Про NavigationProperty сейчас почитаю, спасибо! А про перепроектирование БД и про обычное свойство и Flags можно подробнее? Речь же о поле БД? Какого типа оно будет? (я с postgres работаю, если это имеет значение)
0
|
Usaga
|
15.03.2017, 18:44
#4
|
0
|
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,705
|
|
15.03.2017, 18:51 | 5 |
Да, полагаю, это будет целый тип, (int для postgres), хотя с Postgres почти не работал, могу ошибаться.
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
15.03.2017, 18:55 | 6 |
Речь о том, что "по правилам" лучше поддерживать нормализацию данных в БД и на каждый enum иметь в БД таблицу с соответствующими значениями. Тогда целостность данных будет сохранена.
Но многие на это забивают, ибо ENUM - штука (как правило) не редактируемая, и на каждое перечисление заводить по таблице, мягко говоря, лень и избыточно. Поэтому часто просто заводят поле типа INTEGER или аналогичное, где и хранят целочисленное (реже - строковое) представление значения из ENUM. Об этом и речь.
0
|
IamRain
|
15.03.2017, 18:56
#7
|
Не по теме:
0
|
Usaga
|
15.03.2017, 19:02
#8
|
Не по теме: IamRain, ну да, я понял. Но может быть тут мелось в виду "Свойство Множества" - Set Property)))) :D
0
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
15.03.2017, 21:00 [ТС] | 9 |
Usaga, если свойство класса - просто enum, то я конечно его и храню в БД в виде int. Но тут вопрос про свойство класса List<enum> (то есть один ко многим). Это что же, в целом числе отдельные биты уставнавливать? В принципе можно, но наверно не самое красивое решение. Сначала попробую с NavigationProperty что-то придумать.
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
16.03.2017, 04:52 | 10 |
Alexey437, в postrgesql есть тип данных "массив", который со свистом и улюлюканьем подходит под твою задачу.
1
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
20.03.2017, 15:57 [ТС] | 11 |
Не, тип данных массив нарушает принципы реляционной БД. Я пару дней помучался и все-таки наладил, теперь все извлекается. Убрал таблицу propeties, которая описывала enum. Теперь один item просто связывается с несколькими числами с помощью второй таблицы.
На главной странице я просто в виде строки вывожу список значений. Но теперь вопрос как устроить вьюхи create и edit. Там надо чекбоксами делать, чтобы сразу был доступен мультивыбор. Насколько я понимаю, каждому чекбоксу должно соответствовать поле модели типа bool. Если делать просто что-то типа ContainsA (то есть коллекция содержит MyEnum.A), ContainsB и т.д. для каждого значения MyEnum, то это не слишком топорно будет? И будет ли работать в плане вставки в БД? Или может EF какие-то более хитрые и красивые способы знает?
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
20.03.2017, 16:09 | 12 |
Alexey437, чекбоксы нужно отправлять на сервер в виде массива одно типа данных. В твоём случае, скорее всего чисел.
Добавлено через 8 минут Делается это примерно так. Только тип тега нужно другой - checkbox, но вы додумаетесь как надо.
2
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
20.03.2017, 18:39 [ТС] | 13 |
Usaga, спасибо, интересная ссылка, пригодится на будущее. Но не придумал как ее к данному случаю применить. У меня ведь чекбоксы олицетворяют коллекцию, которая является только одним из полей класса Item. И в качестве параметра метода POST я получаю целиком объект Item. Как же туда еще какой-то массив передать?
Пока сделал таки ContainsA, ContainsB, ... и оно даже работает! Только не очень красиво выглядят эти Contains в классе - почти одинаковый код повторяется 6 раз (у меня в enum 6 значений)
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
21.03.2017, 02:56 | 14 |
Сообщение было отмечено Alexey437 как решение
Решение
Alexey437, звучик как какая-то ерунда. Перечисление всегда должно быть представлено одним полем, либо в виде единственного значения, либо в виде набора флагов. У тебя же ни то, ни другое.
Если у тебя должно быть только шесть значений\признаков, которые могут быть одновременно, то это уже однозначно флаги, которые могут поместиться в один байт. Значит и хранить это дело можно в БД в таблице самой сущности в виде однобайтового поля (uint8 или аналогичного), без отдельных таблиц. Париться о нормализации и реляционности данных в таком случае смысла не имеет. Представить данные признаки в представлении можно именно массивом булевых значений. Суть в том, что тебе понадобится две модели: одна - модель уровня данных (то, что из БД вытаскивается), вторая - модель представления (то, что будет использоваться для вывода\ввода пользователю). Т.е. нужно на каждом логическом уровне представлять одни и теже данные наиболее удобным для этого уровня образом. Т.е. это должно выглядеть так: ты вытаскиваешь и БД оригинальную запись с флагами, создаёшь объект модели для представления, копируешь из оригинального объекта данные, попутно конвертируя нужные поля (в данном случае: байт флагов в массив из шести элементов) и уже адаптированные данные отображаешь пользователю в представлении. Соответственно, обратный процесс аналогичен. Так и только так и добъёшься и удобного хранения данных в БД и удобного же их отображения в представлении (в случае, когда одна модель неудобна для всех её применений, как у тебя).
0
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
21.03.2017, 10:16 [ТС] | 15 |
Ну я немного выше упоминал возможность варианта с отдельными битами, тогда никто не сказал, что это единственно правильное решение. Теперь я уже сделал по-другому и все с нуля переделывать не буду.
Вообще тут жаль, что в C# нет возможности передавать параметр в свойство, тогда не нужно было бы писать отдельное свойство для каждого значения enum и все было бы идеально. Ну либо помогла бы возможность в строго типизированном представлении привязывать не к свойству, а к методу класса. Что тоже невозможно, насколько я понимаю.
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
21.03.2017, 10:59 | 16 |
Alexey437, ну, до твоего последнего сообщения не было до конца ясно, что именно и как ты хочешь сделать. Вот и сомневались.
Вот это непонятно, что имелось в виду. Перечисление можно использовать как набор флагов в одном поле\свойстве. Зачем могло понадобиться заводить по полю на значение?..
0
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
||||||
21.03.2017, 11:22 [ТС] | 17 | |||||
У меня строго типизированное представление. Чекбоксы я создаю так
@Html.CheckBoxFor(model => model.PropertyA, false) @Html.CheckBoxFor(model => model.PropertyB, false) @Html.CheckBoxFor(model => model.PropertyC, false) Оно работает, но для красоты хочется чтобы было типа такого @Html.CheckBoxFor(model => model.Property(MyEnum.A), false) @Html.CheckBoxFor(model => model.Property(MyEnum.B), false) @Html.CheckBoxFor(model => model.Property(MyEnum.C), false) чтобы в классе Property не дублировать. Как именно в представление можно передать одно свойство вместо шести? Надо ведь как-то параметр передать, иначе как чекбокс поймет за какое значение он отвечает? Добавлено через 9 минут Сейчас попробовал индексатор приделать к коллекции. Что-то типа
@Html.CheckBoxFor(model => model[(int)MyEnum.A], false) но такой вариант почему-то не работает. Компилируется и запускается, но в индексатор даже не заходит.
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
||||||
21.03.2017, 12:16 | 18 | |||||
Alexey437, ты, видимо, меня не понял, когда я говорил про разные модели и преставление свойства в виде массива. Грубо говоря, это можно было бы сделать так:
Кликните здесь для просмотра всего текста
И выводить чекбоксы в цикле для всех значений массива. И при получении модели назад, в виде запроса, выполнять обратное преобразование. Добавлено через 3 минуты И при создании чекбоксов с помощью хелпера, указывать им одно имя (если брать мой фрагмент кода - Properties), тогда значения чекбоксов прийдут в виде того же массива (я давал ссылку на эту тему) внутри модели.
1
|
0 / 0 / 0
Регистрация: 26.06.2016
Сообщений: 35
|
|
21.03.2017, 12:42 [ТС] | 19 |
Спасибо, попробую.
А почему на заработал мой индексатор, не знаешь? Просто интересно.
0
|
12079 / 8388 / 1281
Регистрация: 21.01.2016
Сообщений: 31,601
|
|
21.03.2017, 12:52 | 20 |
Alexey437, я не знаю, что скрывается за методами, которые вызываеются в индексаторе. В любом случае, такой подход неудачен. Предложенный мной тоже, наверное, не самый лучший, но всё же.
0
|
21.03.2017, 12:52 | |
21.03.2017, 12:52 | |
Помогаю со студенческими работами здесь
20
Доступ из элемента коллекции к другим элементам коллекции Анонимные коллекции в другие коллекции, как? Комбобокс и коллекции. Или коллекции комбобоксов Удаление коллекции объектов из коллекции Заменить элементы одной коллекции на элементы другой коллекции Коллекции Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |