CTE (общее табличное выражение) в EFCore
У меня есть таблица в моей БД, в которой хранится иерархия местоположений. Имеет 3 колонки
(Id, Name, ParentId)
. Мне нужно загрузить базу строк по условию и всех их родителей до корня. Если бы это было в ADO, я бы использовал следующее утверждение.
with Temp
as
(
select * from Locations where Name like '%filter%'
union all
select Locations.*
from Temp join Locations on Temp.ParentId = Locations.Id
)
select * from Temp
Я использую EFCore и, выполнив несколько поисков, нашел, как Entity Framework работает с рекурсивными иерархиями? Include(), похоже, не работает с ним, как выполнить рекурсивную загрузку с помощью Entity framework? и куча других, которые все старые.
Все найденные мной решения либо жестко закодировали глубину иерархии (используя
Include
) или выполните рекурсию на C#. Все это установлено, мой вопрос в том, что является лучшим решением для этого?
я могу использовать
FromSqlRaw
(Что-то вроде следующего кода), однако мне не нравится писать запросы вручную на C#.
var locations = DataContext.Locations
.FromSqlRaw("MyQuery").ToList();
Я использую
EFCore 3.1.7
2 ответа
Стандартные CTE не поддерживаются в EF Core, см. проблему № 26486 . Однако библиотека linq2db поддерживает CTE и ее можно подключить к EF Core .
Есть вещи, которые EF и EF Core просто не могут сделать.
Рекурсивные CTE - одно из них.
Извините, но вам просто нужно использовать необработанный sql - вы можете либо сделать его функцией db, либо поместить sql в свой код C#. У обоих подходов есть свои преимущества и недостатки:
- Включение его в код упрощает изменение и отслеживание в элементе управления кодом (возможно, git?)
- Помещение его в базу данных как функцию позволит базе данных лучше оптимизировать ее - хотя до какой степени потребуется комментарий эксперта по sql.
Честно говоря, не тратьте зря время, пытаясь сделать то, что просто невозможно.
С уважением,
Адам.