Как вы моделируете древовидную иерархию в Entity Framework? - PullRequest
2 голосов
/ 08 июня 2011

Мне было поручено создать новую систему, которая моделирует виртуальную файловую систему.Мой клиент поручил, чтобы это было построено с использованием Entity Framework.Ранее я обрабатывал подобные объектам структуры данных, но никогда не использовал Entity Framework.

Каков наилучший подход для построения иерархического класса в Entity Framework?Под иерархическим я подразумеваю, что у класса может быть родительский элемент одного типа и может иметь ноль или более дочерних элементов одного типа.

Я использую SQL Server 2008 и Entity Framework 4.0.Должен ли я использовать тип данных встроенной иерархии, или я иду по маршруту ParentID?Предложения будут приветствоваться.

Ответы [ 2 ]

6 голосов
/ 28 июля 2011

У меня была такая же проблема. Я обнаружил, что лучший способ работать с типом иерархии и при этом использовать 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

Я создал все необходимые индексы и ограничения для таблиц. В моем решении представление отображает данные из других таблиц, и процедуры также управляют этими таблицами.

Одед

3 голосов
/ 08 июня 2011

Вы должны использовать ParentID, потому что тип данных иерархии не поддерживается EF (вы также можете проверить описанный обходной путь). В любом случае будьте готовы написать хранимые процедуры, потому что загрузка иерархий с помощью EF обычно трудна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...