2008-09-04 19 views
5

Tengo una tabla de Categorías autorreferencial. Cada categoría tiene un ID de categoría, un ID de categoría de padre, un nombre de categoría, etc. Y cada categoría puede tener cualquier cantidad de subcategorías, y cada una de esas subcategorías puede tener cualquier cantidad de subcategorías, y así sucesivamente. Entonces, básicamente, el árbol puede tener niveles X profundos.LINQ to SQL para tablas autorreferenciales?

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

Esto se siente como un problema recursivo. ¿Es mejor usar un Procedimiento almacenado en su lugar?

Respuesta

3

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

1

Bueno, aquí hay una implementación terrible y apresurada con LINQ. No utilice este :-)

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

El enfoque performant es crear una pieza de inserción/modificar/borrar disparador que mantiene una tabla completamente diferente que contiene pares de nodos-antepasado de todos los antepasados ​​de todos los nodos. De esta manera, la búsqueda es O (N).

Para utilizarlo para obtener todos los productos que pertenecen a un nodo y todos sus descendientes, puede seleccionar todos los nodos de categoría que tienen su nodo de destino como antecesor. Después de esto, simplemente selecciona cualquier producto que pertenezca a cualquiera de estas categorías.

1

La forma en que manejo esto es mediante el uso de algunos métodos de extensión (filtros). He escrito un código de muestra de un proyecto en el que he implementado esto. Mire específicamente las líneas donde estoy poblando un objeto ParentPartner y una Lista de Subpartes.

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

Creo que esta es una gran idea, pero me sale un error al intentar implementar esto. Dice que los métodos de extensión "WithPartnerId" no tienen traducción soportada a SQL. ¿Algunas ideas? –