Linq to SQL Вложенные объекты - PullRequest
2 голосов
/ 14 марта 2011

У меня есть объект под названием Category, который имеет Id, Name и OwnerId. Затем я вкладываю их в подкатегории. Если категория имеет идентификатор владельца, это подкатегория. Количество подкатегорий не ограничено, но у каждого элемента может быть только 1 родитель. Достаточно просто.

Моя проблема в том, что мне нужно получить доступ к подкатегории после загрузки. Как получить категорию «Владение» с помощью Linq. Я знаю Идентификатор Владельца, но я не знаю, сколько глубин может быть владелец.

В основном я ищу способ получить категорию или подкатегорию, где Id == X, но это может быть в подкатегории 6 уровней или более.

Я пытаюсь избежать цикла для каждой подкатегории в каждой подкатегории ....

Ответы [ 2 ]

1 голос
/ 16 марта 2011

Существует другой способ хранения / извлечения древовидной иерархии, как описано в этом fogbugz сообщении в блоге:

Оказывается, там довольно круто Решение этой проблемы объясняется Джо Селько. Вместо того, чтобы пытаться поддерживать кучу родителей / детей отношения по всей вашей базе данных - что потребовало бы рекурсивных SQL-запросов, чтобы найти все потомки узла - мы отмечаем каждый регистр с «левым» и «правым» значением рассчитывается путем обхода дерева в глубину и считать по ходу. «левое» значение узла устанавливается всякий раз, когда оно впервые виден во время обхода, и «правильное» значение устанавливается при ходьбе резервное копирование дерева от узла. Картина, вероятно, имеет больше смысла:

enter image description here

Модель вложенного набора SQL позволяет нам добавлять тематические иерархии без ущерба производительность.

Как это помогает? Теперь мы просто спрашиваем для всех случаев с «левым» значением от 2 до 9, чтобы найти все потомки Б в один пост, проиндексированы запрос. Предки G найдены запрашивая узлы с "слева" меньше, чем 6 (собственные "слева") и "правые" больше чем 6. Работает во всех базах данных. Значительно увеличивает производительность - особенно при запросе большого Иерархии

Вот еще один пост , посвященный более подробно. Он написан с использованием Sql и php, но я думаю, что вы можете понять суть этого и легко перевести в Linq на Sql.

0 голосов
/ 14 марта 2011

В MS SQL 2005 и выше вы можете создавать рекурсивные запросы.Однако в LINQ to SQL вам не повезло.Без реструктуризации данных в базе данных невозможно обойти дерево за один вызов базы данных.

Однако ... я могу придумать один обходной путь.Когда вы можете сгруппировать все Category элементы одного дерева (или части дерева) вместе, вы можете предварительно загрузить эту часть полного дерева в одном операторе.После этого вы сможете пройти эту часть дерева, не вызывая новые вызовы в базу данных.Это будет выглядеть примерно так:

// Load the category that will be used as starting point.
var subCategory = db.Categories.Single(c => c.Id == 56);

// Performance: Load the complete group in one go.
var categories = (
    from category in db.Categories
    where category.GroupId == subCategory.GroupId
    select category)
    .ToArray();

// Traverse the tree and get the top-most parent (if any).
var parent = subCategory.GetParents().LastOrDefault();

// Extension method to get the parents.
public static IEnumerable<Category> GetParents(
    this Category category)
{
    while (category.Parent != null)
    {
        // NOTE: cat.Parent will not cause a database call
        // when the Parent is already loaded by L2S.
        yield return cat.Parent;
        category = category.Parent;
    }
}

Это, конечно, будет работать только в том случае, если вы сможете определять элементы как группу.Будет ли это решение быстрее, также зависит от размера группы.Когда группа объектов, которые вы загружаете (и не используете), очень велика, это фактически замедляет работу приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...