Chciałbym skonfigurować widok i powiązaną funkcję opartą na tabeli na podstawie CTE. Moje rozumowanie jest takie, że chociaż można wdrożyć logikę po stronie aplikacji, będzie to wymagało wysłania pośrednich danych przez przewód w celu obliczenia w aplikacji. Za pomocą projektanta DBML widok przekształca się w encję tabeli. Następnie można powiązać tę funkcję z jednostką Table i wywołać metodę utworzoną w DataContext, aby wyprowadzić obiekty typu zdefiniowanego przez widok. Korzystanie z funkcji opartej na tabelach umożliwia mechanizmowi zapytania uwzględnienie parametrów podczas konstruowania zestawu wyników, zamiast stosowania warunku w zestawie wyników zdefiniowanym w widoku po fakcie.
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]
Aby go użyć by zrobić coś podobnego - zakładając jakiś rozsądny schemat nazewnictwa:
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...
}
}
Próbowałem takiej funkcji i wydaje się, że jest to właściwa droga. I może być wywołany z LINQ, dołączony do datacontext. Dlaczego zarówno widok, jak i funkcja? - wydają się być duplikowane. – Anthony
Funkcja nie mapuje tego samego schematu co tabela. Obejmuje poziom. Jeśli nie masz dodanej kolumny, możesz zmapować ją bezpośrednio na stół. Zakładałem, że poziom w hierarchii jest ważny. – tvanfosson