我正在使用Kentico的第8版,我有一个自定义文档/页面,它有一个唯一的数字标识字段,遗憾的是这个数据来自现有的源码,因为我无法在使用时设置页面耦合数据的主键ID API我被迫拥有这个单独的领域。
如果节点的类名匹配,我确保在使用DocumentEvents.Insert.Before
的{{1}}事件期间该字段是新的且唯一的。所以我也处理了工作流我也为{{实现了相同的方法1}}。
这在创建新项目时效果很好,无论是否我们尝试复制现有节点,源node.SetValue("ItemIdentifier", newIdentifier);
都保持不变。我希望我可以排除该字段被复制,但我还没有找到一个例子。
所以我继续实施了一个解决方案,以确保在通过处理WorkflowEvents.SaveVersion.Before
和Identifier
来复制节点时创建新的标识符。
不幸的是在我的情况下,来自这些事件arg的DocumentEvents.Copy.Before
是无用的,我无法为我的生活修改字段,当我打开IlSpy我意识到原因时,节点复制方法抓住了一个新的副本总是来自数据库的节点!因此,如果要在复制节点之前修改字段,则呈现DocumentEvents.Copy.After
将无用。
所以我改为在e.Node
中传递标识符,使插入进一步在循环中处理,以生成克隆节点的新标识符。
不幸的是,我不知道,如果我们复制一个已发布的节点,那么数据库上的值是正确的,但它的NodeXML值不是。
这个IMO听起来像一个Kentico错误,它要么保留源节点的NodeXML /版本,要么由于某种原因DocumentEvents.Copy.Before
在RequestStockHelper
上无法正常工作,因为它是已发布的工作流节点。< / p>
有人遇到类似的问题吗?有没有其他方法我可以将字段配置为唯一的数字标识字段,这不是主键,并在插入时自动递增?或者从复制过程中排除一个字段?
答案 0 :(得分:1)
作为一种可能的解决方案,您是否可以在DocumentEvents.Copy.Before
中创建新文档并从复制的文档中复制值,然后取消复制事件本身?
答案 1 :(得分:0)
好的,事实证明这不是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;
}