2008-09-04 6 views
5

Ich habe eine Tabelle mit sich selbst referenzierenden Kategorien. Jede Kategorie hat eine CategoryID, ParentCategoryID, CategoryName usw. Jede Kategorie kann eine beliebige Anzahl von Unterkategorien haben, und jede dieser Unterkategorien kann eine beliebige Anzahl von Unterkategorien haben, und so und so weiter. Also im Grunde kann der Baum X Ebenen tief sein.LINQ to SQL für selbstreferenzierende Tabellen?

Dann sind die Produkte den Blatt (unter) Kategorien zugeordnet. Gibt es eine Möglichkeit, mit LINQ to SQL alle Produkte für eine bestimmte Kategorie zu erhalten (also alle Produkte, die mit allen Blattnachfahren verknüpft sind)?

Das fühlt sich wie ein rekursives Problem an. Ist es besser, stattdessen eine gespeicherte Prozedur zu verwenden?

Antwort

3

Ich glaube nicht, linq-to-sql hat eine gute Antwort auf dieses Problem. Da Sie SQL Server 2005 verwenden, können Sie CTEs für hierarchische Abfragen verwenden. Entweder eine gespeicherte Prozedur oder eine Inline-Abfrage (mit DataContext.ExecuteQuery) wird den Zweck erfüllen.

1

Nun, hier ist eine schrecklich überstürzte Implementierung mit LINQ. Verwenden Sie dieses :-) nicht

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

Der performant Ansatz ist ein Insert/ändern/löschen Auslöser zu schaffen, die eine ganz andere Tabelle unterhält die Knoten-Vorfahren Paare für alle Vorfahren aller Knoten enthält. Auf diese Weise ist die Suche O (N).

Um alle Produkte, die zu einem Knoten und allen seinen Nachkommen gehören, zu erhalten, können Sie einfach alle Kategorieknoten auswählen, die Ihren Zielknoten als Vorfahren haben. Danach wählen Sie einfach alle Produkte aus, die zu einer dieser Kategorien gehören.

1

Die Art, wie ich das handhabe, ist mit einigen Erweiterungsmethoden (Filter). Ich habe einen Beispielcode aus einem Projekt geschrieben, auf dem ich dies implementiert habe. Sehen Sie sich speziell die Zeilen an, in denen ich ein ParentPartner-Objekt und eine SubPartners-Liste bevölkere.

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

Ich denke, dies ist eine großartige Idee, aber ich erhalte eine Fehlermeldung, wenn sie versuchen, dies zu implementieren. Es besagt, dass die Erweiterungsmethoden "WithPartnerId" keine unterstützte Übersetzung in SQL unterstützen. Irgendwelche Ideen? –