#.net #sql-server-2008 #entity-framework
#.net #sql-server-2008 #entity-framework
Вопрос:
Мне было поручено создать новую систему, которая моделирует виртуальную файловую систему. Мой клиент обязал, чтобы это было построено с использованием Entity Framework. Я раньше обрабатывал узлоподобные структуры данных, но никогда с Entity Framework.
Какой наилучший подход к созданию иерархического класса в Entity Framework? Под иерархическим я подразумеваю, что класс может иметь родительского элемента того же типа и может иметь ноль или более дочерних элементов того же типа.
Я использую SQL Server 2008 и Entity Framework 4.0. Должен ли я использовать встроенный тип данных иерархии или мне следует использовать родительский идентификатор? Предложения будут только приветствоваться.
Ответ №1:
У меня была та же проблема. Я обнаружил, что лучший способ работать с типом данных 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 и получить хорошую производительность и аккуратный код.
Это хранимая процедура add, которую я использую:
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
Ответ №2:
Вы должны использовать ParentID, потому что тип данных hierarchyid не поддерживается EF (вы также можете проверить описанный обходной путь). В любом случае будьте готовы к написанию хранимых процедур, потому что загрузка иерархий с помощью EF обычно сложна.