复制 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.Before
和 DocumentEvents.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;
}
我使用的是 Kentico 的第 8 版,我有一个自定义 document/page,它有一个唯一的数字标识字段,不幸的是,这些数据来自现有来源,因为我无法设置页面的主键 ID使用 API 时的耦合数据我被迫拥有这个单独的字段。
如果节点的 class 名称匹配,我使用 node.SetValue("ItemIdentifier", newIdentifier);
确保在 DocumentEvents.Insert.Before
事件期间该字段是新的且唯一的,等等。所以工作流也被处理我也实现了WorkflowEvents.SaveVersion.Before
.
这在创建新项目时效果很好,无论我们尝试复制现有节点,源 Identifier
都保持不变。我希望我可以排除该字段被复制,但我还没有找到这样的例子。
所以我继续实施了一个解决方案,以确保在通过处理 DocumentEvents.Copy.Before
和 DocumentEvents.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;
}