Используйте Linq для запроса терминальных / конечных узлов в иерархической таблице / Составном шаблоне

StackOverflow https://stackoverflow.com/questions/414945

Вопрос

У меня есть таблица с самоссылками с идентификатором, CategoryName и ParentID .Это типичный сценарий иерархической таблицы категорий, которые сами по себе могут быть разделены на категории, которые, по словам экспертов DB, называются моделью смежности.

Что я хочу, так это использовать Linq to SQL для запроса подкатегорий, которые сами по себе не связаны ни с какими другими подкатегориями, т. Е. Они являются непосредственными конечными узлами некоторой заданной категории или подкатегории.

У меня есть самая простая часть, которая заключается в том, чтобы просто получить подкатегории.Почти стесняюсь помещать сюда код.Но нам действительно нравится видеть код..

IList<Categories> subcategories = context.Where( c => c.ParentId == 1).ToList();  

Но сужение списка до категорий без подкатегорий меняет меня.Любая помощь была бы высоко оценена.

Спасибо вам за помощь.Джефф

Обновить** Казалось бы, это работает, но если бы кто-нибудь мог подтвердить, что это "правильно", я был бы благодарен.Итак, если я хочу, чтобы конечные узлы относились к категории с Id = 1, я бы сделал это:

Categories.Where( c => !c.Children.Any ( d => d.ParentId == c.Id)).Where( e => e.ParentId == 1) 

"Дети" - это название, которое Linq дает самоссылающейся ассоциации.

Это было полезно?

Решение

Ваше решение правильное, потому что Any() метод, преобразующий в sql функцию "EXISTS()" и !c.Children.Any ( d => d.ParentId == c.Id)) преобразуется в предложение sql , аналогичное NOT EXISTS (SELECT * FROM Categories WHERE ParentID = outerRef.ID)

Другой способ сделать это - использовать Count :

Categories.Where( c => c.Children.Count(d => d.ParentId == c.Id) == 0).Where( e => e.ParentId == 1)

Но обычно EXISTS() предпочтительнее COUNT() в sql (по соображениям производительности), поэтому решение с помощью Any() должно быть правильным.

Другие советы

Я думаю, если я правильно понимаю ваш вопрос, вы пытаетесь получить все дочерние элементы, у которых нет собственных дочерних элементов...этот запрос самостоятельно соединяет таблицу с самим собой, чтобы проверить, используется ли узел в качестве родительского, если это не так, то он отображается в результате.

Я не уверен, работает ли это, поскольку мне не на чем это проверить...

   (from c in context
    join cc in context on c.id equals cc.parentid into temp
    from t in temp.DefaultIfEmpty()
    where t == null
    select c).ToList()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top