Removing a component associated with many items

I have a component that is associated with many thousands of elements (in this case, all other elements are components). Is there an easy / quick way to remove a component and remove all links?

I am currently using Tridion 5.3 and doing this programmatically through the TOM API. For one component that was associated with 10,000 other components, this took about 7 hours. I need a lot more!

Now I'm moving from R5.3 in 2011, so I can use it either for the task.

The code I use is as follows:

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
source share
2 answers

Using a script through TOM is the best way to do this. The Core Service API in Tridion 2011 is probably not much faster.

In my experience, it is best to use TOM through Interop in .NET.

  • Explicitly declare all objects and release them. For instance:

     // 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)) { // ... } 
  • If you pass an object to a method, pass the URI instead of the object and declare a new instance of the object inside the method and explicitly publish it inside the method.

  • Declare one instance of TDSE and reference it. Creating multiple instances is a more expensive option.

  • Where used can be time consuming and hard on the database. Update database indexes and run maintenance scripts before running code.

+5
source

It seems that you run two garbage collections every time you process the component. This will almost certainly affect your performance quite a bit.

As for the TOM, most of the important things were said by others, although I don't think anyone mentioned that ItemField collections are incredibly slow compared to using the XML API to do the same job. In other words, load the XmlDocument (or possibly XDocument) with GetXml () ... directly manipulate the XML, paste it back with UpdateXml () and Save.

+3
source

All Articles