O LINQ to SQL para a auto-tabelas de referência?
-
09-06-2019 - |
Pergunta
Eu tenho uma auto-referência a tabela de Categorias.Cada Categoria tem uma CategoryID ParentCategoryID, Nomedacategoria etc.E cada categoria pode ter qualquer número de sub-categorias, e cada uma dessas sub-categorias podem ter qualquer número de sub-categorias, e o e e assim por diante.Então, basicamente, a árvore pode ser X níveis de profundidade.
Em seguida, os Produtos são associados a folha (sub) Categorias.Existe uma maneira de obter todos os Produtos para uma determinada Categoria (o que seria todos os produtos associados a todas as suas folhas descendentes) usando LINQ to SQL?
Este se sente como uma recursiva do problema.É melhor usado um Procedimento Armazenado em vez disso?
Solução
Eu não acho que o linq para sql, tem uma boa resposta para esse problema.Desde que você está usando o sql server 2005, você pode usar CTEs para fazer consultas hierárquicas.Um procedimento armazenado ou uma linha de consulta (usando o DataContext.ExecuteQuery) irá fazer o truque.
Outras dicas
Bem, aqui está uma terrível correu implementação usando LINQ.Não use isso :-)
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
A performance abordagem é criar um inserir/modificar/excluir gatilho que mantém um modo totalmente diferente de tabela que contém o nó ancestral pares para todos os antepassados de todos nós.Desta forma, a pesquisa é O(N).
Para usá-lo para obter todos os produtos pertencentes a um nó e todos os seus descendentes, você pode apenas selecionar todos os nós categoria que tem o seu nó de destino como um ancestral.Após isso, basta selecionar qualquer um dos produtos pertencentes a qualquer uma destas categorias.
A maneira de eu lidar com isso é usando alguns métodos de extensão (filtros).Eu tenho escrito alguns códigos de exemplo a partir de um projeto que implementou isto.Procurar especificamente nas linhas onde eu estou preencher um ParentPartner objeto e um SubPartners Lista.
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;
}