How to effectively isolated ContentPartRecord properties for use in different versions

Topics: Writing modules
Nov 20, 2014 at 7:09 PM
I'm looking for guidance on how deal with ContentPartRecords as they are updated from module version to version.

Here's the setup...
1) V1 record class and corresponding part
2) V1 migration code simply calls Create and returns 1
3) In Create, the code setups ups parts and content types as needed. Example data is created in the Create method as well. This allows users to turn on the module and get a nice start on the functionality.

So far so good - everything works as expected.

Now, let's update the record class.

Initially, I wanted to make sure the upgrade scenario was working. This meant using the UpdateFrom methodology in the migrations code. Work included...

a. Add new properties to the record
b. Call AlterTable to add necessary columns

From a starting point of version 1, this was working.

The final test case was a clean install.

Suddenly, the creation process bombs. I can see all of the data calls to create and alter parts and types hit the db. However, the system never records that my create process was successful and everything is rolled back.

Investigation found that failures all stem from the fact that storage APIs take my V2 record class definition and create calls with the V2 properties even though the V1 code is effectively running. In the Create method (v1) the call to Insert a row has a column from V2, but at that point in time the backing table doesn't know about the V2 column b/c the UpdateFrom method hasn't run. I'm now in a catch-22. I can't effectively add data in v1 because NHibernate is using the full definition of the class.

Here's a pseudo code outline...

public class MyRecord : ContentPartRecord {
  public virtual int V1Prop { get; set; }


public class Migrations : DataMigrationImpl {
  public int Create() {
    // Create Table, add column for V1Prop
    // Setup fields, parts, types
    // Add data
    try {
      var test = contentManager.New(Constants.ContentTypeName);
      test.As<MyPart>().V1Prop = 1;
    catch (Exception e) {
      // silently ignore - data population should never break setup
    return 1;
Then the V2 stuff looks like...

public class MyRecord : ContentPartRecord {
  public virtual int V1Prop { get; set; }
  public virtual int V2Prop { get; set; }


// Add UpdateFrom1 method
public int UpdateFrom1() {
  // AlterTable and do other stuff
Again, this all works if the starting point is a previously provisioned instance of v1. If I take this code to a clean install, the Create method never registers as having completed because the Record class doesn't match the table created (btw, this was incredibly hard to find in the debugger - I had to first find the problem in SQL and slowly work my way back).

A close look found the following:
  1. Even though my calls to create new content types in Create are fully wrapped to prevent any exceptions from breaking the Create method, the exceptions are still picked up by Orchards exception handler. Can anyone explain why this would happen?
  2. More importantly, can someone shed some light on how to update ContentPartRecords so that we can effectively list which properties should be used for a query and/or version?