2011-06-08 105 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加载层次结构通常很困难。