We have a small command line application we modify as needed to update schemas.
We use core services to call GetListXML
on the folder containing the components we want to update:
public XElement GetAllComponents(string folderUri)
{
var filter = new OrganizationalItemItemsFilterData()
{
ItemTypes = new[] { ItemType.Component },
Recursive = true
}
return CORE_SERVICE.GetListXml(folderUri, filter);
}
We then have a simple loop that iterates through each component, checks to see if it uses the schema we want to update and if so we call a simple method to update the schema used by the component (both the starting folder and schema we're updating come from the app's config file but could as easily come from a command line argument.)
We change the code of this method slightly based on what we're trying to update. For instance if we just want to pickup a new field added to the schema we just do a checkout and checkin of the component like so (note we do conduct a simple check to make sure we're only updating 'parent' level components):
public bool UpdateComponentSchema(string componentId)
{
try
{
// get parent level from componentId: tcm:12-234
var parentLevel = componentId.Split(':')[1].Split('-')[0];
var parentLocLevel = string.Format("-{0}-", parentLevel);
var com = CORE_SERVICE.Read(componentId, new ReadOptions()) as ComponentData;
var parentLocation = com.BluePrintInfo.OwningRepository.IdRef;
// check parent location
if (!parentLocation.Contains(parentLocLevel))
return true;
var component = CORE_SERVICE.TryCheckOut(componentId, null) as ComponentData;
if (component != null)
{
try
{
CORE_SERVICE.CheckIn(componentId, null);
}
catch (FaultException fEx)
{
if (!fEx.Message.ToLower().Equals("the item is not checked-out.")) throw fEx;
}
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
Interestingly, if you update a schema this way the last modified date of the components don't even change.
If we want to update new fields with a specific value we can easily add code to do that after the code that does the component check-out.
We use the same general concept if we need to perform some sort of bulk update/modification of values in components that cannot be handled from within the CME.
We also perform extensive logging around the calls to UpdateComponentSchema so that we have a good record of the successes and failures. If needed we can have someone go back after the fact and touch the failures by hand but in general as long as we've made sure all components are checked in prior to running the app this runs pretty smoothly.
Usually we have our team in Hyderabad run these types of batch processing jobs for us as they are working during times when our United States based editors and producers are not editing content in the CME.