Вопрос

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

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

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

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

Решение

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

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

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

public IQueryable GetCategories(Category parent)
{
    var cats = (parent.Categories);
    foreach (Category c in cats )
    {
        cats  = cats .Concat(GetCategories(c));
    }
    return a;
}

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

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

Я справляюсь с этим, используя некоторые методы расширения (фильтры).Я написал несколько примеров кода из проекта, в котором я это реализовал.Посмотрите конкретно на строки, где я заполняю объект 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;
        }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top