LINQ to SQL per tabelle autoreferenziali?
-
09-06-2019 - |
Domanda
Ho una tabella Categorie autoreferenziale.Ogni categoria ha un CategoryID, ParentCategoryID, CategoryName, ecc.E ogni categoria può avere un numero qualsiasi di sottocategorie, e ciascuna di queste sottocategorie può avere un numero qualsiasi di sottocategorie, e così via.Quindi in pratica l'albero può essere profondo X livelli.
Quindi i Prodotti vengono associati alle (sotto)categorie fogliari.Esiste un modo per ottenere tutti i prodotti per una determinata categoria (che sarebbero tutti i prodotti associati a tutti i suoi discendenti foglia) utilizzando LINQ to SQL?
Sembra un problema ricorsivo.È meglio utilizzare invece una Stored Procedure?
Soluzione
Non penso che linq-to-sql abbia una buona risposta a questo problema.Poiché stai utilizzando SQL Server 2005, puoi utilizzare CTE per eseguire query gerarchiche.Una procedura memorizzata o una query in linea (utilizzando DataContext.ExecuteQuery) basterà.
Altri suggerimenti
Bene, ecco una terribile implementazione affrettata utilizzando LINQ.Non usarlo :-)
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
L'approccio performante consiste nel creare un trigger di inserimento/modifica/eliminazione che mantenga una tabella completamente diversa che contiene coppie nodo-antenato per tutti gli antenati di tutti i nodi.In questo modo, la ricerca è O(N).
Per usarlo per ottenere tutti i prodotti appartenenti a un nodo e tutti i suoi discendenti, puoi semplicemente selezionare tutti i nodi di categoria che hanno il tuo nodo target come antenato.Successivamente, seleziona semplicemente i prodotti appartenenti a una di queste categorie.
Il modo in cui lo gestisco è utilizzando alcuni metodi di estensione (filtri).Ho scritto del codice di esempio da un progetto su cui ho implementato questo.Guarda in particolare le righe in cui sto compilando un oggetto ParentPartner e un elenco di 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;
}