4

使用我在网上找到的示例,我创建了一个函数,该函数使用 GetReparentedValue 重新设置子项。

但是,当我运行代码时,出现以下错误:无法在对象中插入重复键。

我明白为什么(因为我正在尝试让孩子重新成为父母,而新父母已经有了孩子,所以我需要知道新父母结构中孩子的 MAX 路径(层次结构),但我不明白我实际上是怎样的打算这样做。

路径 0x58

旧路径 0x

新路径 0x68

SqlCommand command = new SqlCommand("UPDATE Structure SET " +
                                    "Path = " + path + ".GetReparentedValue" +
                                    "(" +
                                      oldPath + ", " + newPath +
                                    ")" +
                                    "ParentID = @id " +
                                    "WHERE Path = " + path, _connection);

添加孩子时我必须这样做,所以我认为需要将其添加到上面的查询中,但我不知道在哪里path + ".GetDescendant(" + lastChildPath + ", NULL)

数据库表

StructureID   int                         Unchecked  
Path          hierarchyid                 Unchecked  
PathLevel     ([Path].[GetLevel]())       Checked  
Description   nvarchar(50)                Checked  
ParentID      int                         Checked  
ParentPath    ([Path].[GetAncestor]((1))) Checked  

有人有什么建议吗?

提前感谢您的帮助:-)

克莱尔

4

2 回答 2

3

您可以进行一些更改以使其正常工作。首先,您不需要oldPath表示要移动的节点的父级的 。在.GetReparentedValue函数中,您输入正在移动的节点的 hierarchyid,即 中的值path

第二个更改是添加另一个 SELECT 语句来应用您的GetDescendant函数。这是一个示例脚本,您可以在 SQL Server Management Studio (SSMS) 中尝试,或者更改以合并到您的 SQLCommand 调用中。前几行(变量声明是赋值)仅用于在 SSMS 中运行。您会将最后一个语句SELECTUPDATE语句传输到调用代码。

DECLARE @Path hierarchyid
DECLARE @oldPath hierarchyid
DECLARE @newPath hierarchyid
SELECT @Path=0x58, @oldPath=0x, @newPath=0x68

SELECT @newPath = @newPath.GetDescendant(MAX(Path), NULL)
FROM Structure
WHERE path.GetAncestor(1)=@newPath;

UPDATE Structure
SET Path = Path.GetReparentedValue(@Path, @newPath)
WHERE Path = @Path;

您的UPDATE声明和此修订版只会重新成为单个节点的父节点。它不会自动移动移动节点的子节点。移动节点的子节点将成为孤立节点。

如果您需要移动选定的节点和该节点的所有后代,您可以使用前面语句的以下变体。

DECLARE @Path hierarchyid
DECLARE @oldPath hierarchyid
DECLARE @newPath hierarchyid
SELECT @Path=0x58, @oldPath=0x, @newPath=0x68

SELECT @newPath = @newPath.GetDescendant(MAX(Path), NULL)
FROM Structure
WHERE Path.GetAncestor(1) = @newPath ;

UPDATE Structure
SET Path = Path.GetReparentedValue(@Path, @newPath)
WHERE Path.IsDescendantOf(@Path) = 1;

实际上,从第一个脚本到这个脚本的唯一变化是在最后一行。该Path.IsDescendantOf(@Path) = 1测试适用于 的所有后代@Path,包括@Path. 更新后将保持层次关系。

于 2010-11-06T01:09:54.357 回答
0

这是移动子树及其所有子树的另一个示例。它与公认的答案基本相同。这取自文档

CREATE PROCEDURE MoveOrg(@oldMgr nvarchar(256), @newMgr nvarchar(256) )  
AS  
BEGIN  
DECLARE @nold hierarchyid, @nnew hierarchyid  
SELECT @nold = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @oldMgr ;  

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE  
BEGIN TRANSACTION  
SELECT @nnew = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @newMgr ;  

SELECT @nnew = @nnew.GetDescendant(max(OrgNode), NULL)   
FROM HumanResources.EmployeeDemo WHERE OrgNode.GetAncestor(1)=@nnew ;  

UPDATE HumanResources.EmployeeDemo    
SET OrgNode = OrgNode.GetReparentedValue(@nold, @nnew)  
WHERE OrgNode.IsDescendantOf(@nold) = 1 ;  

COMMIT TRANSACTION  
END ;  
GO
于 2018-10-19T11:16:01.993 回答