Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
3 / 3 / 0
Регистрация: 07.11.2018
Сообщений: 119
MS SQL

Как красиво получить объект с подсчетом связанных данных

25.07.2022, 02:42. Показов 2739. Ответов 30

Студворк — интернет-сервис помощи студентам
Возьму для примера объект Album у которого связь с объектами Image.
Мне нужно на сайт вернуть альбомы с количеством фото внутри.
Я знаю как это сделать, но мне не нравятся мои варианты реализации.

Я использую [NotMapped] поля для дополнительных данных в объекте модели.
Первый вариант.
C#
1
2
3
4
5
6
7
8
9
10
var res = _context.Albums.Where(x => x.AccountId == id)
                           .Include(x => x.Images.Take(1))
                           .Select(x => new
                           {
                               Album = x,
                               ImagesCount = x.Images.Count
 
                           }).ToList();
            res.ForEach(x => x.Album.ImagesCount = x.ImagesCount);
            return res.Select(x => x.Album);
Здесь приходится 2 раза перебирать дополнительные поля.

Второй вариант
Перебрать все поля в новый объект, но учитывая массивность некоторых объектов я его не использую.

Третий вариант
Вернуть кортеж с 2 объектами (Альбом + Объект с деталями сущности)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
var res = _context.Albums.Where(x => x.AccountId == id)
                           .Include(x => x.Images.Take(1))
                           .Select(x => new
                           {
                               Album = x,
                               Details = new AlbumDetails
                                             {
                                                   ImagesCount = x.Images.Count
                                                   /*Тут бывает много полей*/
                                             }
 
                           }).ToList();
            return (res.Select(x => x.Album), res.Select(x => x.Details));
Здесь уже нет 2 переборов и [NotMapped] полей, но появляется необходимость использовать AutoMapper 2 раза для превращения в DTO.

По итогу я бы хотел видеть реализацию наподобие этой, но увы это не сработает, так как IQueryable не поддерживает тело в Select.
C#
1
2
3
4
5
6
7
return _context.Albums.Where(x => x.AccountId == id)
                           .Include(x => x.Images.Take(1))
                           .Select(x =>
                           {
                               ImagesCount = x.Images.Count,
                               return x;
                           });
Как сделать то что мне нужно красиво?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.07.2022, 02:42
Ответы с готовыми решениями:

Подключил базу данных sql как оформить красиво?
Ребят как сделать красиво таблицы которые я подключил к бд? у меня есть форма в которой я ввожу данные и 8 таблиц в которой данные...

Получить адрес на переменную\объект, потом от этого адреса создать указатель на объект и изменить значение. Как?
int a=55; uintptr_t adr=&a; int *b=*adr; *b=88; cout << "a=" << a << "b=" << b; Добавлено через 16 минут так...

PHP и вывод значений из базы данных как оформить красиво
значения из бд MySQL я знаю как выводить (но вывожу их строками - как в текстовом редакторе:D ) к примеу $rs = mysql_query($strSQL); ...

30
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
26.07.2022, 16:05
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Nuril Посмотреть сообщение
При получении альбома я ограничиваю фото внутри до 1 элемента
Тогда это уже к вопросу о более корректном именовании. Т.е. в данном случае стоит назвать коллекцию не 'Images', а 'PreviewImages', а общее количество обозначить через 'TotalImagesCount'. Или вовсе, если у вас там всегда строго одно изображение, согласно требованиям к API, вместо коллекции сделать свойство 'public ImageDto PrevieImage { get; set; }'.

Потому как вернётесь вы к этому коду через месяц-другой и придётся тратить время, дабы понять что вы там имели ввиду, и почему в коллекции 'Images' всегда только одно изображение, когда в базе их 12.

Добавлено через 7 минут
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А что может потянуть класс данных в EF? Аннотации? Дак они не из из библиотек EF, они из System.
Да, точно. Но мне всё равно очень не нравится практика, когда структура данных всех слоёв приложения жёстко привязана к структуре БД, и когда ты не можешь просто добавить в таблицу поле, не спровоцировав его распространение через всё приложение. Не можешь удалить какое-то устаревшее поле из базы, т.к. оно опубликовано в API и ты без понятия, кто и как его может использовать (из внешних клиентов).

Плюс, если в API потребуются (мне всегда требуются) какие-то методы, которые оперируют ограниченными/объединёнными наборами данных, то рядом всё равно вырастет слой DTO. И приложение станет более запутанным, т.к. часть API будет привязана к БД, а часть не будет.

P.S.: вероятно, в каких-то случаях такая модель и применима, но я с подобным на практике не сталкивался.
0
3 / 3 / 0
Регистрация: 07.11.2018
Сообщений: 119
26.07.2022, 16:12  [ТС]
Andrey-MSK, хмм
Цитата Сообщение от kotelok Посмотреть сообщение
Подобное применимо далеко не всегда, т.е. это скорее редкий частный случай.
Выглядит удобно, чтобы не делать DTO в DAL.
Цитата Сообщение от kotelok Посмотреть сообщение
вынести классы EF-сущностей в отдельную сборку
У меня сущности уже вынесены в сборку Domain
Цитата Сообщение от kotelok Посмотреть сообщение
реализовать EF-контекст исключительно через fluent-API
Тут нужно перенести разве что аннотации [Required], всё остальное уже там.

Цитата Сообщение от kotelok Посмотреть сообщение
И в вашем примере 'AlbumDto' не должен содержать в себе коллекцию 'Image' (это ведь в вашем случае EF-сущность?).
И я могу спокойно нарушить это?


Цитата Сообщение от kotelok Посмотреть сообщение
не 'Images', а 'PreviewImages'
До этого в этом же объекте я передавал и множество фото когда открываю его.
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,765
Записей в блоге: 4
26.07.2022, 16:17
kotelok, Не, то что описывает БД - это описание можно использовать везде где требуются именно эти наборы. Для индивидуальных наборов, можно там же, в DAL, создать свои классы и использовать их так же по всему приложению. Ведь, как пример, для обработки данных в VM, вы всё равно создаёте индивидуальные свойства и поля класса, которые взаимодействуют с классами данных. Так что практически во всех случаях, если приложение работает с БД, то вся БЛ модели находится в БД, а приложение это просто показать, отредактировать и записать назад. Никаких сложных преобразований и расчётов оно практически никогда не выполняет... С этим гораздо быстрее справится сервер SQL, или сервер приложений, чем калькулятор у клиента...
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,088
26.07.2022, 17:58
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Ну у вас же БД выступает моделью, зачем вам еще плодить кучу DTO? У вас ведь есть класс данных, который описывает таблицу или VIEW. Вот его и можно гонять по всему приложению
Знакомые слова человека не работавшего с крупным проектом на EF)

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А что может потянуть класс данных в EF?
Неконсистентность, неприменимость и угробленную производительность.

Неконсистеность. В том плане, что сущности не будут содержать полный граф зависимостей, кроме тривиальных случаев. Т.е. вам либо придётся на ВСЕ возможные навигационные свойства вызывать Include, либо уповать на Lazy Loading. Первое приведёт к генерации запроса на выгребание всей базы (граф зависимостей, особенно со стороны статических справочников, может покрывать ВСЁ хранилище) с соответствующим вылетом. Второе - к лютым тормозам и расходам памяти на раздутый кеш контекста.

Что вы с этим будете делать? Правильно, явно выгружать только какие-то отдельные свойства. Получается, что ваши сущности не будут содержать всех данных, о которых их контракт заявляет. А там поди угадай почему коллекция заказов у юзера пустая. Толи нет заказов, толи забыли Include указать. Просто простор для багов.

Неприменимость. Вам может понадобиться запросить из базы то, что в сущности отсутствует. Более того: оно даже не относится к сущности. О чём тут ТС и спросил. Начинать в сущность пихать разные игнорируемые свойства? Запашком не отдаёт?

Производительность. На практике, любой бизнес-процесс требует только подмножество полей любой таблицы или JOIN'а таблиц. Выгребая всё подряд, вы рискуете запросить и "тяжёлые" поля. Типа NVARCHAR(MAX), BLOB или какие-то вычисляемые поля. А это и доступ к данным на уровне базы и пересылка по сети, и материализация на клиенте. Вы когда на чистом SQL запросы пишете, тоже всегда делаете SELECT *? Как, классно работает?)

Правильный подход тут только один - проекции. Сущности EF'а - только схема базы данных. Не DTO для реального выгребания данных.
1
403 / 265 / 69
Регистрация: 12.04.2020
Сообщений: 1,404
26.07.2022, 18:18
а что мешает подрубить дапер и написать простой запрос в базу, и вернуть результат какой хотите?
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,088
27.07.2022, 03:50
Dr9vik, человек учится использовать EF...
1
403 / 265 / 69
Регистрация: 12.04.2020
Сообщений: 1,404
27.07.2022, 13:12
Цитата Сообщение от Usaga Посмотреть сообщение
человек учится использовать EF...
написать sql запрос используя любых 3 метода что есть в EF
попытка сделать то что хочет автор через Linq - извращение
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,765
Записей в блоге: 4
27.07.2022, 14:09
Цитата Сообщение от Dr9vik Посмотреть сообщение
и да
советую все таки прочитать про Entity Framework
многие вещи будут еще проще, работа с базой, апгрейд(миграции) и тд
можно использовать Linq для запроса в базу, притом что вы нистрочки sql запроса не напишите
Цитата Сообщение от Dr9vik Посмотреть сообщение
написать sql запрос используя любых 3 метода что есть в EF
попытка сделать то что хочет автор через Linq - извращение
Как-то вы быстро переобулись
0
403 / 265 / 69
Регистрация: 12.04.2020
Сообщений: 1,404
27.07.2022, 14:27
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Как-то вы быстро переобулись
где противоречие?
автор хочет узнать количество
Linq просто так не даст эту возможность
смысл страдать?
темболее если взять тот же postgres, то оверхед написать просто Count, придётся писать костыли...
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,765
Записей в блоге: 4
27.07.2022, 14:40
Nuril,
Можно просто написать SP и отразить её на класс EF, что, кстати, будет гораздо проще и быстрее работать, чем огород из LINQ.
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,088
28.07.2022, 17:59
Цитата Сообщение от Dr9vik Посмотреть сообщение
автор хочет узнать количество
Linq просто так не даст эту возможность
LINQ не даст, или вы не знаете как это сделать? Это разные вещи.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.07.2022, 17:59

Как получить DataTable из двух связанных таблиц?
У меня есть DataSet, включающий две связанные таблицы. Мне нужно получить на выходе DataTable - выборку из этих двух таблиц. Перерыл...

Как, используя рефлексию, получить перечень событий, связанных с той же кнопкой?
Не имя события- имя события и дурак получит. А само событие! Ну то есть: создадим форму и кинем на неё кнопку. using System; using...

Получить std::tm из time_point, или как избежать ошибок ODR, связанных с использованием time_t
Всем привет! Есть код: // функция не делает поправки на часовой пояс ::std::tm getGMT(const ::std::time_t time)...

Как сделать отображение определенных связанных данных в DataGridView2
Есть 2 таблицы table1 и table2. 1 в DataGridView1 в которой 2 колонки, к примеру ID и Name. Нужно чтоб при выборе в DataGridView1 ID с...

Как выполнить AR Запрос в Yii на выборку записей по значению связанных данных?
Добрый день, Есть 2 таблицы: m_bids ------------ id mc_points ------------


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru