Frage

Ich habe eine selbstreferenzierende Kategorientabelle.Jede Kategorie hat eine CategoryID, ParentCategoryID, CategoryName usw.Und 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.Im Grunde kann der Baum also X Ebenen tief sein.

Anschließend werden Produkte Blatt-(Unter-)Kategorien zugeordnet.Gibt es eine Möglichkeit, mithilfe von LINQ to SQL alle Produkte für eine bestimmte Kategorie abzurufen (das wären alle Produkte, die allen ihren Blattnachkommen zugeordnet sind)?

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

War es hilfreich?

Lösung

Ich glaube nicht, dass Linq-to-SQL eine gute Antwort auf dieses Problem hat.Da Sie SQL Server 2005 verwenden, können Sie CTEs verwenden, um hierarchische Abfragen durchzuführen.Entweder eine gespeicherte Prozedur oder eine Inline-Abfrage (mit DataContext.ExecuteQuery) reicht aus.

Andere Tipps

Nun, hier ist eine schrecklich überstürzte Implementierung mit LINQ.Benutze das nicht :-)

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

Der performante Ansatz besteht darin, einen Einfüge-/Änderungs-/Lösch-Trigger zu erstellen, der eine völlig andere Tabelle verwaltet, die Knoten-Vorfahren-Paare für alle Vorfahren aller Knoten enthält.Auf diese Weise ist die Suche O(N).

Um damit alle Produkte zu erhalten, die zu einem Knoten und allen seinen Nachkommen gehören, können Sie einfach alle Kategorieknoten auswählen, deren Vorfahr Ihr Zielknoten ist.Anschließend wählen Sie einfach alle Produkte aus, die zu einer dieser Kategorien gehören.

Ich gehe damit um, indem ich einige Erweiterungsmethoden (Filter) verwende.Ich habe Beispielcode aus einem Projekt geschrieben, in dem ich dies implementiert habe.Schauen Sie sich insbesondere die Zeilen an, in denen ich ein ParentPartner-Objekt und eine SubPartners-Liste fülle.

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;
        }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top