Pregunta

Tengo una tabla de Categorías de autorreferencia.Cada categoría tiene un CategoryID, ParentCategoryID, CategoryName, etc.Y cada categoría puede tener cualquier número de subcategorías, y cada una de esas subcategorías puede tener cualquier número de subcategorías, y así sucesivamente.Básicamente, el árbol puede tener X niveles de profundidad.

Luego, los productos se asocian a las (sub)categorías de hoja.¿Hay alguna manera de obtener todos los productos para una categoría determinada (que serían todos los productos asociados a todos sus descendientes de hoja) usando LINQ to SQL?

Esto parece un problema recursivo.¿Es mejor utilizar un procedimiento almacenado?

¿Fue útil?

Solución

No creo que linq-to-sql tenga una buena respuesta a este problema.Como está utilizando SQL Server 2005, puede utilizar CTE para realizar consultas jerárquicas.Ya sea un procedimiento almacenado o una consulta en línea (usando DataContext.ExecuteQuery) funcionará.

Otros consejos

Bueno, aquí hay una implementación terriblemente apresurada usando LINQ.No uses esto :-)

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

El enfoque eficaz es crear un activador de inserción/modificación/eliminación que mantenga una tabla completamente diferente que contenga pares nodo-ancestro para todos los ancestros de todos los nodos.De esta manera, la búsqueda es O(N).

Para usarlo para obtener todos los productos que pertenecen a un nodo y todos sus descendientes, simplemente puede seleccionar todos los nodos de categoría que tengan su nodo objetivo como antepasado.Después de esto, simplemente seleccione cualquier producto que pertenezca a cualquiera de estas categorías.

La forma en que manejo esto es mediante el uso de algunos métodos de extensión (filtros).Escribí un código de muestra de un proyecto en el que implementé esto.Mire específicamente las líneas donde estoy completando un objeto ParentPartner y una lista de 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;
        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top