У меня есть саморегулирующаяся таблица категорий. У каждой категории есть CategoryID, ParentCategoryID, CategoryName и т. д. И каждая категория может иметь любое количество подкатегорий, и каждая из этих подкатегорий может иметь любое количество подкатегорий и так далее. Таким образом, дерево может иметь глубину X уровней.
Затем Товары связываются с конечными (подкатегориями). Есть ли способ получить все продукты для любой данной категории (которые будут всеми продуктами, связанными со всеми ее конечными потомками) с помощью LINQ to SQL?
Это похоже на рекурсивную проблему. Лучше вместо этого использовать хранимую процедуру?

Вот ужасная поспешная реализация с использованием LINQ. Не используйте это :-)
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
Эффективный подход заключается в создании триггера вставки / изменения / удаления, который поддерживает совершенно другую таблицу, содержащую пары узел-предок для всех предков всех узлов. Таким образом, поиск выполняется за O (N).
Чтобы использовать его для получения всех продуктов, принадлежащих узлу и всем его потомкам, вы можете просто выбрать все узлы категорий, у которых ваш целевой узел является предком. После этого вы просто выбираете любые продукты, относящиеся к любой из этих категорий.
Я не думаю, что у linq-to-sql есть хороший ответ на эту проблему. Поскольку вы используете sql server 2005, вы можете использовать CTE для выполнения иерархических запросов. Либо хранимая процедура, либо встроенный запрос (с использованием DataContext.ExecuteQuery) сделают свое дело.
Я справляюсь с этим, используя некоторые методы расширения (фильтры). Я написал пример кода из проекта, в котором реализовал это. Обратите особое внимание на строки, в которых я заполняю объект 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;
}
Я думаю, что это отличная идея, но я получаю сообщение об ошибке при попытке ее реализовать. В нем говорится, что методы расширения WithPartnerId не поддерживают преобразование в SQL. Есть идеи?