如何在Entity Framework中建模树层次结构?

时间:2011-06-08 09:38:17

标签: .net sql-server-2008 entity-framework

我的任务是构建一个模拟虚拟文件系统的新系统。我的客户已经强制要求使用Entity Framework构建它。我之前处理过类似节点的数据结构,但从未处理过Entity Framework。

在Entity Framework中构建分层类的最佳方法是什么?通过分层,我的意思是一个类可以拥有相同类型的父类,并且可以有零个或多个相同类型的子类。

我正在使用SQL Server 2008和Entity Framework 4.0。我应该使用内置层次结构数据类型,还是使用ParentID路由?建议是最受欢迎的。

2 个答案:

答案 0 :(得分: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-to-Entities并获得良好的性能和整洁的代码。

这是我使用的添加存储过程:

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

我在表上创建了所有需要的索引和约束。在我的解决方案中,视图显示来自其他表的数据,并且过程也操纵这些表。

乌迪德

答案 1 :(得分:3)

您必须使用ParentID,因为hierarchyid data type is not supported by EF(您还可以检查所描述的解决方法)。无论如何,准备编写存储过程,因为使用EF加载层次结构通常很难。