08 Feb 2011

If one of your field data type needs to be changed, you will run into issues when deploying the new version of your application, as SharePoint can’t translate from one data type to another. For example, if you change a field type from “Single Line of Text” to “Notes” in Fields.xml, everything will go wrong.

The clean way to do this is to create a new field, the one that will be used from now on, and copy the value of the old field to the new field, while applying a transformation if necessary.

For this, we wrote a generic method that will go trough the entire site and perform the changes on the specified fields.

public static void CopyFieldValues(SPSite site,
    String copyFromFieldInternalName,
    String copyToFieldInternalName,
    Func<Object, Object> transformation)
{
    foreach (SPWeb web in site.AllWebs)
    {
        //Get all the ListItems in every list of the web that has the 2 fields
        var items = (from l in web.Lists.Cast<SPList>()
                     where l.Fields.ContainsField(copyFromFieldInternalName)
                         && l.Fields.ContainsField(copyToFieldInternalName)
                     from i in l.Items.Cast<SPListItem>()
                     select i).ToList();

        //For each listitem in this web, migrate the content of the old one to the new one
        //To do this, we use the tranformation Func that was given as a parameter
        foreach (SPListItem item in items)
        {
            item[copyToFieldInternalName] = transformation(item[copyFromFieldInternalName]);

            //Do system update to avoid modifying the item's version
            item.SystemUpdate(false);
        }
    }
}

So, now that we have a generic method to copy the content of a field into another, we can “specialize” it for various uses.

One example is migrating a Single Line of Text type field to a Note type field. It is very easy because there is no transformation needed:

public static void CopyFieldValuesFromSingleLineOfTextToNote(SPSite site,
    String copyFromFieldInternalName,
    String copyToFieldInternalName)
{
    //No need to transform the data in this case
    SharePointFieldsHelper.CopyFieldValues(site, copyFromFieldInternalName, copyToFieldInternalName, oldFieldValue => oldFieldValue);
}


blog comments powered by Disqus