Thursday 6 November 2014

Converting an Orchard ContentPartRecord to a ContentPartVersionRecord

Suppose you have an existing part record which is not versioned which you would like to be versioned. It is possible to migrate the record to be versioned, but it does take a bit of fiddling.

This was originally written for Orchard 1.6, so probably won't work for the new Document repository backed properties in 1.8+.

Steps

  1. Create a new 'versioned' copy of the class.

    Be sure to leave the existing record class for the moment.

        [Obsolete("Replaced with 'ContentGroupChildVersionPartRecord' to enable versioning of this content")]
        public class ContentGroupChildPartRecord : ContentPartRecord {
            public virtual int Weight { get; set; }
            public virtual bool ShowInCombinedFeed { get; set; }
        }
    
        public class ContentGroupChildVersionPartRecord : ContentPartVersionRecord
        {
            public virtual int Weight { get; set; }
            public virtual bool ShowInCombinedFeed { get; set; }
        }
    
  2. Create a table for the new record in migrations, using the command 'ContentPartVersionRecord' as you would normally do for creating a versioned record.

     
    public int UpdateFrom18()
    {
     SchemaBuilder.CreateTable(childTableVersionedName,
      table => table
       .ContentPartVersionRecord()
       .Column<int>("Weight")
       .Column<bool>("ShowInCombinedFeed")
     );
    
     return 19;
    }
    
  3. Manually extrapolate version records from the existing records, creating rows in the database for each relevant version record.

    You only need to run this code once.

    var childRepo = WorkContext.Resolve<IRepository<ContentGroupChildPartRecord>>();
    var childVersionedRepo = WorkContext.Resolve<IRepository<ContentGroupChildVersionPartRecord>>();
    
    foreach (ContentGroupChildPartRecord row in childRepo.Table)
    {
     foreach (var version in row.ContentItemRecord.Versions) {
      var newItem = new ContentGroupChildVersionPartRecord()
      {
       ContentItemRecord = row.ContentItemRecord,
       ContentItemVersionRecord = version,
       Weight = row.Weight,
       ShowInCombinedFeed = row.ShowInCombinedFeed
      };
      childVersionedRepo.Create(newItem);
     }
    }
    
  4. Change all relevant references in your code to point to the new versioned record class instead of the old non-versioned record class.

    E.g. public class ContentGroupChildPart : ContentPart<ContentGroupChildPartRecord>
    becomes
    public class ContentGroupChildPart : ContentPart<ContentGroupChildVersionPartRecord>
  5. (Optional) Delete the old table, remove the old class and any references in your code.