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.

Честно говоря, не тратьте зря время, пытаясь сделать то, что просто невозможно.

С уважением,

Адам.

Другие вопросы по тегам