2008-09-04 4 views
5

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

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

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

ответ

3

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

1

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

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

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

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

1

То, как я справляюсь с этим, - это использовать некоторые методы расширения (фильтры). Я написал пример кода из проекта, который я реализовал. Посмотрите конкретно на строки, где я заполняю объект 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; 
     } 
+0

Я думаю, что это отличная идея, но я получаю сообщение об ошибке при попытке реализовать это. В нем говорится, что методы расширения «WithPartnerId» не поддерживают перевод на SQL. Есть идеи? – 2009-03-09 20:29:45

Смежные вопросы