Configuraría una vista y una función asociada basada en tablas basada en el CTE. Mi razonamiento para esto es que, si bien podría implementar la lógica en el lado de la aplicación, esto implicaría enviar los datos intermedios a través del cable para el cálculo en la aplicación. Usando el diseñador de DBML, la vista se traduce en una entidad de tabla. A continuación, puede asociar la función con la entidad Tabla e invocar el método creado en el DataContext para derivar objetos del tipo definido por la vista. El uso de la función basada en tablas permite que el motor de consultas tenga en cuenta los parámetros al construir el conjunto de resultados en lugar de aplicar una condición en el conjunto de resultados definido por la vista después del hecho.
CREATE TABLE [dbo].[hierarchical_table](
[id] [int] IDENTITY(1,1) NOT NULL,
[parent_id] [int] NULL,
[data] [varchar](255) NOT NULL,
CONSTRAINT [PK_hierarchical_table] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE VIEW [dbo].[vw_recursive_view]
AS
WITH hierarchy_cte(id, parent_id, data, lvl) AS
(SELECT id, parent_id, data, 0 AS lvl
FROM dbo.hierarchical_table
WHERE (parent_id IS NULL)
UNION ALL
SELECT t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl
FROM dbo.hierarchical_table AS t1 INNER JOIN
hierarchy_cte AS h ON t1.parent_id = h.id)
SELECT id, parent_id, data, lvl
FROM hierarchy_cte AS result
CREATE FUNCTION [dbo].[fn_tree_for_parent]
(
@parent int
)
RETURNS
@result TABLE
(
id int not null,
parent_id int,
data varchar(255) not null,
lvl int not null
)
AS
BEGIN
WITH hierarchy_cte(id, parent_id, data, lvl) AS
(SELECT id, parent_id, data, 0 AS lvl
FROM dbo.hierarchical_table
WHERE (id = @parent OR (parent_id IS NULL AND @parent IS NULL))
UNION ALL
SELECT t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl
FROM dbo.hierarchical_table AS t1 INNER JOIN
hierarchy_cte AS h ON t1.parent_id = h.id)
INSERT INTO @result
SELECT id, parent_id, data, lvl
FROM hierarchy_cte AS result
RETURN
END
ALTER TABLE [dbo].[hierarchical_table] WITH CHECK ADD CONSTRAINT [FK_hierarchical_table_hierarchical_table] FOREIGN KEY([parent_id])
REFERENCES [dbo].[hierarchical_table] ([id])
ALTER TABLE [dbo].[hierarchical_table] CHECK CONSTRAINT [FK_hierarchical_table_hierarchical_table]
Para usarlo que haría algo así como - si se asume algún esquema de nomenclatura razonable:
using (DataContext dc = new HierarchicalDataContext())
{
HierarchicalTableEntity h = (from e in dc.HierarchicalTableEntities
select e).First();
var query = dc.FnTreeForParent(h.ID);
foreach (HierarchicalTableViewEntity entity in query) {
...process the tree node...
}
}
He probado una función como esta, y parece ser el camino a seguir. Y se puede llamar desde LINQ, adjunto al contexto de datos. Además, ¿por qué tanto la vista como la función? - parecen ser una duplicación – Anthony
La función no asigna el mismo esquema que la tabla. Incluye el nivel. Si no tiene la columna agregada, puede asignarla directamente a la tabla. Supuse que el nivel en la jerarquía era importante. – tvanfosson