2011-06-08 103 views
2

我的任務是構建一個模擬虛擬文件系統的新系統。我的客戶已要求使用實體框架構建。我之前處理過類似節點的數據結構,但從來沒有處理過Entity Framework。如何在實體框架中建模樹層次結構?

什麼是在實體框架中構建分層類的最佳方法?通過層次結構,我的意思是一個類可以有一個相同類型的父類,並且可以有零個或多個相同類型的子類。

我正在使用SQL Server 2008和Entity Framework 4.0。我應該使用內置的層次結構數據類型,還是使用ParentID路線?建議將是最受歡迎的。

回答

6

我有同樣的問題。我發現處理hierarchyid數據類型並仍然使用EF 4.0的最佳方法是在層次結構表上構建一個視圖。

由於視圖不可更新,我創建了一個刪除,插入和添加存儲過程並將它們映射到ORM中的實體映射。這工作真的很好。

比方說你有這個表:

CREATE TABLE [dbo].[NodeHierarchy] 
(
[Node] hierarchyid NOT NULL, 
[NodeId] int NOT NULL, 
[Level] AS ([Node].[GetLevel]()) PERSISTED, 
[Lineage] AS ([Node].[ToString]()) PERSISTED, 
[RootNode] AS ([Node].[GetAncestor]([Node].[GetLevel]() - 1)) PERSISTED, 
[ParentNode] AS ([Node].[GetAncestor](1)) PERSISTED 
) 

現在你在它創建這樣的觀點:

CREATE VIEW [dbo].[NodeHierarchyView] 
AS 
SELECT ch.NodeId AS [NodeId], 
     ch.Node.ToString() AS [Lineage], 
ch.[Level] AS [Level], 
chr.Node.ToString() AS [RootLineage], 
chr.NodeId AS [RootNodeId], 
chp.Node.ToString() As [ParentLineage], 
chp.NodeId AS [ParentNodeId] 
FROM  dbo.NodeHierarchy ch 
LEFT OUTER JOIN NodeHierarchy chr ON 
     ch.RootNode = chr.Node 
LEFT OUTER JOIN CompanyHierarchy chp ON 
     ch.ParentNode = chp.Node 

現在我可以在模型在視圖中創建一個實體,並使用LINQ到實體並獲得良好的性能和整潔的代碼。

這是附加存儲過程使用:

CREATE PROCEDURE [dbo].[AddNode] 
@NodeId int, 
@ParentNodeId int 
AS 
DECLARE @NewNode hierarchyid; 
DECLARE @ParnetLineage nvarchar(4000); 

SELECT @ParnetLineage = Lineage 
FROM NodeHierarchy 
WHERE NodeId = @ParentNodeId 

IF @ParnetLineage IS NULL 
BEGIN 
    SET @ParnetLineage = N'/'; 
END 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
BEGIN TRANSACTION 
    SET @NewNode = CAST(@ParnetLineage + CAST(@NodeId AS nvarchar (4000)) + N'/' AS hierarchyid); 

    INSERT NodeHierarchy (Node, NodeId) 
    VALUES (@NewNode, @NodeId) 
COMMIT 

SELECT @NodeId AS [NewNodeId] 
RETURN 0 

我創建了所有需要的索引和約束在表中。在我的解決方案中,視圖顯示來自其他表的數據,並且過程也操縱這些表。

Oded

3

您必須使用ParentID,因爲hierarchyid data type is not supported by EF(您也可以查看描述的解決方法)。無論如何,要準備編寫存儲過程,因爲使用EF加載層次結構通常很困難。