4

何千ものアイテムにリンクされているコンポーネントがあります(この場合、他のすべてのアイテムはコンポーネントです)。コンポーネントを削除してすべてのリンクを削除する簡単で迅速な方法はありますか?

私は現在Tridion5.3を使用しており、TOMAPIを介してプログラムでこれを行っています。10000の他のコンポーネントにリンクされた1つのコンポーネントの場合、これには約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を介してスクリプトを使用するのが、それを行うための最良の方法です。Tridion2011のコアサービス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の単一インスタンスを宣言し、それを参照します。複数のインスタンスを作成することは、より高価なオプションです。

  • 使用場所は時間がかかる可能性があり、データベースに負荷がかかります。コードを実行する前に、データベースインデックスを更新し、メンテナンススクリプトを実行します。

于 2012-12-05T11:58:03.250 に答える
3

コンポーネントを処理するたびに、2つのガベージコレクションがトリガーされているように見えます。これはほぼ確実にパフォーマンスに大きな影響を与えます。

TOMに関しては、重要なことのほとんどは他の人から言われていますが、XML APIを使用して同じ仕事をする場合に比べて、ItemFieldコレクションが非常に遅いとは誰も言っていないと思います。つまり、GetXml()を使用してXmlDocument(またはおそらくXDocument)をロードします... XMLを直接操作し、UpdateXml()を使用して押し戻し、保存します。

于 2012-12-05T14:16:59.500 に答える