Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Как создать рекурсивный запрос к БД с помощью Entity Framework?

#c_sharp #sql_server #entity_framework


Здравствуйте, у меня есть проблема. Есть таблица категорий, которая выглядит так:


Задача при выборе категории высшей иерархии подтянуть все его подкатегории - создать
коллекцию категорий дерева. 
Вопрос такой: как реализовать такую задачу с помощью Entity Framework? Возможно ли
сделать это одним запросом к БД? 

За любую помощь буду признателен)
    


Ответы

Ответ 1



Entity Framework не умеет в рекурсивные запросы. Но проблему решить можно. Вариант 1: Сделать view на основе рекурсивного запроса на SQL используя WITH CTE. После чего в коде вызывать получение данных из этой вью. Примерный код SQL: CREATE VIEW [dbo].[vw_Subcategories] AS WITH cte ( CategoryID, SubcatID) AS ( SELECT Id AS SubcatID, RootId as CategoryID FROM dbo.TableName UNION ALL SELECT e.Id AS SubcatID, cte.Id AS CategoryID FROM cte INNER JOIN dbo.TableName AS e ON e.RootId = cte.Id ) Вариант 2: Сделать простой отдельный рекурсивный метод в коде для получения дочерних EF-объектов: List GoDownRecursive(int categoryId) { var res = new List(); foreach(var subcategory in DbContext.Cateogires.Where(c => c.RootId == categoryId) { res.Add(subcategory); res.AddRange(GoDownRecursive(subcategory.Id)); } return res; } Запросов к базе будет больше, но если вложенность небольшая и запрос не самый частый, то вариант приемлимый. При желании полученные деревья можно кэшировать.

Ответ 2



Entity прекрасно работает с хранимыми процедурами на стороне SQL - попробуйте их! Плюсы: Потенциальный выигрыш в производительности, потому что все промежуточные выборки происходят на стороне SQL. Минусы: Дополнительное "распыление" бизнес-логики.

Ответ 3



Ну, почему бы не сделать так: в entity для категории завести список подкатегорий, и отключить для них lazy loading? Здесь описаны методы отключения lazy loading, как полностью, так и для конкретных свойств или вообще лишь на одну операцию. Скорее всего, вам подойдёт просто var categories = context.Categories.Include("SubCategories").ToList();

Комментариев нет:

Отправить комментарий