4

我有一个链接到数千个项目的组件(在这种情况下,所有其他项目都是组件)。是否有一种简单/快速的方法来删除组件并删除所有链接?

我目前正在使用 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();
    }
}
4

2 回答 2

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 实例并引用它。创建多个实例是一个更昂贵的选择。

  • Where Used 可能需要很长时间并且对数据库来说很重。在运行代码之前更新数据库索引并运行维护脚本。

于 2012-12-05T11:58:03.250 回答
3

每次处理组件时,您似乎都会触发两次垃圾回收。这几乎肯定会对你的表现产生很大影响。

至于 TOM——大多数重要的事情都已经被其他人说了,尽管我认为没有人提到 ItemField 集合与使用 XML API 完成相同的工作相比非常慢。换句话说,使用 GetXml() 加载 XmlDocument(或者可能是 XDocument)...直接操作 XML,使用 UpdateXml() 将其推回并保存。

于 2012-12-05T14:16:59.500 回答