我有一个链接到数千个项目的组件(在这种情况下,所有其他项目都是组件)。是否有一种简单/快速的方法来删除组件并删除所有链接?
我目前正在使用Tridion 5.3并通过TOM API以编程方式执行此操作。对于与10000个其他组件链接的一个组件,这需要大约7个小时。我还有很多要去的地方!
我正在从R5.3迁移到2011年,因此可以使用任一任务。
我使用的代码如下......
static void Main(string[] args)
{
var componentIDToRemove = "tcm:4-123456";
var linkedComponentIDs = System.IO.File.ReadAllLines("C:\\...\\whereused.txt"); // ids of the components linked to tcm:4-123456
TDS.TDSE tdse = new TDS.TDSE();
foreach (var linkedComponentID in linkedComponentIDs)
{
TDS.Component component = null;
TDS.ItemFieldValues itemFieldValues = null;
try
{
component = (TDS.Component)tdse.GetObject(linkedComponentID, TDSDefines.EnumOpenMode.OpenModeView);
itemFieldValues = component.MetadataFields["myfield"].value;
var itemFieldValuesCount = itemFieldValues.Count;
for (var i = itemFieldValuesCount; i > 0; i--)
{
if (itemFieldValues[i].ID == componentIDToRemove)
{
component.CheckOut();
itemFieldValues.Remove(i);
component.Save();
component.CheckIn();
}
}
}
finally
{
// release the TDS objects from memory
ReleaseObject(component);
ReleaseObject(itemFieldValues);
}
}
}
public static void ReleaseObject(object o)
{
try
{
if (o != null)
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);
}
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
答案 0 :(得分:5)
通过TOM使用脚本是最好的方法。 Tridion 2011中的核心服务API可能没有那么快。
根据我的经验,以下是在.NET中通过Interop使用TOM的最佳实践。
明确声明所有对象并释放它们。例如:
// do this
var items = folder.GetItems(16);
foreach(var item in items)
{
// ...
}
if(items != null)
{
Marshal.FinalReleaseComObject(items);
}
// instead of this
foreach(var item in folder.GetItems(16))
{
// ...
}
如果将对象传递给方法 - 传递URI而不是对象,并在方法中声明对象的新实例,并在方法中明确释放它。
声明TDSE的单个实例并引用它。创建多个实例是一个更昂贵的选择。
使用可能需要很长时间并且数据库很重。在运行代码之前更新数据库索引并运行维护脚本。
答案 1 :(得分:3)
每次处理组件时,您似乎都会触发两个垃圾收集。这几乎肯定会影响你的表现。
关于TOM - 其他人已经说过大多数重要的事情,虽然我认为与使用XML API相比,有些人没有提到ItemField集合令人难以置信地慢同样的工作。换句话说,使用GetXml()加载XmlDocument(或者可能是XDocument)...直接操作XML,使用UpdateXml()将其推回并保存。