LINQ to SQL для самообращающихся таблиц? - PullRequest
5 голосов
/ 04 сентября 2008

У меня есть таблица ссылок на себя. У каждой категории есть CategoryID, ParentCategoryID, CategoryName и т. Д. И у каждой категории может быть любое количество подкатегорий, и у каждой из этих подкатегорий может быть любое количество подкатегорий, и так далее, и так далее. Таким образом, в основном дерево может иметь глубину X уровней.

Тогда продукты связываются с листовыми (под) категориями. Есть ли способ получить все продукты для любой данной категории (которые будут все продукты, связанные со всеми ее потомками листьев), используя LINQ to SQL?

Это похоже на рекурсивную проблему. Лучше вместо этого использовать хранимую процедуру?

Ответы [ 4 ]

3 голосов
/ 04 сентября 2008

Я не думаю, что у linq-to-sql есть хороший ответ на эту проблему. Поскольку вы используете SQL Server 2005, вы можете использовать CTE для выполнения иерархических запросов. Либо хранимая процедура, либо встроенный запрос (с использованием DataContext.ExecuteQuery) сделают свое дело.

2 голосов
/ 04 сентября 2008

Что ж, вот ужасная поспешная реализация с использованием LINQ. Не используйте это: -)

public IQueryable GetCategories(Category parent)
{
    var cats = (parent.Categories);
    foreach (Category c in cats )
    {
        cats  = cats .Concat(GetCategories(c));
    }
    return a;
}
1 голос
/ 05 января 2009

Я справляюсь с этим, используя некоторые методы расширения (фильтры). Я написал пример кода из проекта, на котором я это реализовал. Посмотрите конкретно на строки, где я заполняю объект ParentPartner и список SubPartners.

public IQueryable<Partner> GetPartners()
        {
            return from p in db.Partners
                   select new Partner
                   {
                       PartnerId = p.PartnerId,
                       CompanyName = p.CompanyName,
                       Address1 = p.Address1,
                       Address2 = p.Address2,
                       Website = p.Website,
                       City = p.City,
                       State = p.State,
                       County = p.County,
                       Country = p.Country,
                       Zip = p.Zip,
                       ParentPartner = GetPartners().WithPartnerId(p.ParentPartnerId).ToList().SingleOrDefault(),
                       SubPartners = GetPartners().WithParentPartnerId(p.PartnerId).ToList()
                   };
        }


public static IQueryable<Partner> WithPartnerId(this IQueryable<Partner> qry, int? partnerId)
        {
            return from t in qry
                   where t.PartnerId == partnerId
                   select t;
        }

public static IQueryable<Partner> WithParentPartnerId(this IQueryable<Partner> qry, int? parentPartnerId)
        {
            return from p in qry
                   where p.ParentPartner.PartnerId == parentPartnerId
                   select p;
        }
1 голос
/ 04 сентября 2008

Эффективный подход заключается в создании триггера вставки / изменения / удаления, который поддерживает совершенно другую таблицу, которая содержит пары узел-предок для всех предков всех узлов. Таким образом, поиск O (N).

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

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