复制 Document/Page 排除 field/column 或设置新值

Copy Document/Page excluding field/column or setting new value

我使用的是 Kentico 的第 8 版,我有一个自定义 document/page,它有一个唯一的数字标识字段,不幸的是,这些数据来自现有来源,因为我无法设置页面的主键 ID使用 API 时的耦合数据我被迫拥有这个单独的字段。

如果节点的 class 名称匹配,我使用 node.SetValue("ItemIdentifier", newIdentifier); 确保在 DocumentEvents.Insert.Before 事件期间该字段是新的且唯一的,等等。所以工作流也被处理我也实现了WorkflowEvents.SaveVersion.Before.

的方法相同

这在创建新项目时效果很好,无论我们尝试复制现有节点,源 Identifier 都保持不变。我希望我可以排除该字段被复制,但我还没有找到这样的例子。

所以我继续实施了一个解决方案,以确保在通过处理 DocumentEvents.Copy.BeforeDocumentEvents.Copy.After.

复制节点时创建新标识符

不幸的是,在我的情况下,这些事件参数中的 e.Node 是无用的,我终生无法修改字段,当我打开 IlSpy 时,我意识到了原因,节点复制方法获取了一个新的总是从数据库中复制节点!因此,如果您想在复制节点之前修改字段,则呈现 DocumentEvents.Copy.Before 无用。

所以我改为在 RequestStockHelper 中传递标识符,插入在循环中进一步处理,为克隆的节点生成一个新的标识符。

不幸的是,我不知道,如果我们复制一个已发布的节点,数据库中的值是正确的,但它的 NodeXML 值不是。

这个 IMO 听起来像是一个 Kentico 错误,它要么保留源节点的 NodeXML/version,要么由于某种原因 node.SetValue("ItemIdentifier", newIdentifier);WorkflowEvents.SaveVersion.Before 上无法正常工作,因为它是已发布和工作流节点。

有人遇到过类似的问题吗?有没有其他方法可以将字段配置为唯一的数字标识字段,它不是主键,并且在插入时自动递增?或者从复制过程中排除一个字段?

作为一个可能的解决方案,您能否在 DocumentEvents.Copy.Before 中创建一个新文档并从复制的文档中复制值,然后取消复制事件本身?

好的,事实证明这不是 Kentico 的问题,而是版本保存的方式。

如果您想在 DocumentEvents.Insert.Before 中计算一个唯一值,您需要将其传递给 WorkflowEvents.SaveVersion.Before,因为后者发送的节点与前者的原始节点相同。例如您在 Insert 节点中所做的任何更改都不会发送到 SaveVersion,您需要手动处理。

下面是处理复制场景和插入编译类型新项目的伪代码CineDigitalAV:

protected override void OnInit()
{
    base.OnInit();

    DocumentEvents.Insert.Before += Insert_Before;
    DocumentEvents.Copy.Before += Copy_Before;
    WorkflowEvents.SaveVersion.Before += SaveVersion_Before;

}

private void Copy_Before(object sender, DocumentEventArgs e)
{
    if (e.Node != null)
    {
        SetCopyCineDigitalIdentifier(e.Node);
    }
}

private void SaveVersion_Before(object sender, WorkflowEventArgs e)
{
    if (e.Document != null)
    {
        EnsureCineDigitalIdentifier(e.Document);
    }
}

private void Insert_Before(object sender, DocumentEventArgs e)
{
    if (e.Node != null)
    {
        EnsureCineDigitalIdentifier(e.Node);
    }
}


private void SetCopyCineDigitalIdentifier(TreeNode node)
{
    int identifier = 0;
    if (node.ClassName == CineDigitalAV.CLASS_NAME)
    {
        identifier = node.GetValue<int>("AVCreation_Identifier", 0);

        // flag next insert to create a new identifier
        if (identifier > 0)
            RequestStockHelper.Add("Copy-Identifier-" + identifier, true);
    }
}


private void EnsureCineDigitalIdentifier(TreeNode node)
{
    int identifier = 0;
    if (node.ClassName == CineDigitalAV.CLASS_NAME)
    {
        identifier = node.GetValue<int>("AVCreation_Identifier", 0);
    }

    if (identifier == 0 || (identifier != 0 && RequestStockHelper.Contains("Copy-Identifier-" + identifier)))
    {
        // generate a new identifier for new items ot those being copied
        RequestStockHelper.Remove("Copy-Identifier-" + identifier);
        int newIdentifier = GetNewCineDigitalIdentifierAV(node.NodeSiteName);
        node.SetValue("AVCreation_Identifier", newIdentifier);

        // store the newidentifier so that saveversion includes it 
        RequestStockHelper.Add("Version-Identifier-" + identifier, newIdentifier);
    }
    else if (RequestStockHelper.Contains("Version-Identifier-" + identifier))
    {
        // handle saveversion with value from the insert
        int newIdentifier = ValidationHelper.GetInteger(RequestStockHelper.GetItem("Version-Identifier-" + identifier), 0);
        RequestStockHelper.Remove("Version-Identifier-" + identifier);

        node.SetValue("AVCreation_Identifier", newIdentifier);
    }
}
private int GetNewCineDigitalIdentifierAV(string siteName)
{
    return (DocumentHelper.GetDocuments<CineDigitalAV>()
                            .OnSite(siteName)
                            .Published(false)
                            .Columns("AVCreation_Identifier")
                            .OrderByDescending("AVCreation_Identifier")
                            .FirstObject?
                            .AVCreation_Identifier ?? 0) + 1;
}