Updating Modules after successful build

Topics: Writing modules
Nov 21, 2011 at 4:06 PM

 

I'm trying to figure out how to update my custom module to have new fields. I followed the SimpleCommerce example for building modules, which worked quite well, but now I want to add more fields to the module.

 

Old Code:

Model (Beer.cs)

 

    public class BeerPartRecord : ContentPartRecord
    {
        public virtual string Style { get; set; }
        public virtual float AlcoholByVolume { get; set; }
    }

    public class BeerPart : ContentPart<BeerPartRecord>
    {
        [Required]
        public string Style
        {
            get { return Record.Style; }
            set { Record.Style = value; }
        }

        [Required]
        public float AlcoholByVolume
        {
            get { return Record.AlcoholByVolume; }
            set { Record.AlcoholByVolume = value; }
        }
    }

 

Driver (BeerDriver.cs)

 

    public class BeerDriver : ContentPartDriver<BeerPart>
    {
        protected override DriverResult Display(BeerPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_Beer", () => shapeHelper.Parts_Beer(Name: part.Name, Style: part.Style, AlcoholByVolume: part.AlcoholByVolume)); 
        }

        protected override DriverResult Editor(BeerPart part, dynamic shapeHelper)
        {
            return ContentShape("Parts_Beer_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Beer", Model: part, Prefix: Prefix));
        }

        protected override DriverResult Editor(BeerPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            bool updated = updater.TryUpdateModel(part, Prefix, null, null);
            return Editor(part, shapeHelper);
        }
    }
    

 

View/Parts (Beer.cshtml)

 

<br />
@T("Style"): $@Model.Style <br />
@T("Alcohol by Volume (%)"): $@Model.AlcoholByVolume<br />

 

View/EditorTemplates/Parts (Beer.cshtml)

@model BeerReceipe.Models.BeerPart
<fieldset>
    <label class="sub" for="Style">@T("Style")</label><br />
    @Html.TextBoxFor(m => m.Style, new { @class = "text" })<br />
    <label class="sub" for="AlcoholByVolume">@T("Alcohol by volume (%)")</label><br />
    @Html.TextBoxFor(m => m.AlcoholByVolume, new { @class = "text"})<br />
</fieldset>

Migrations.cs

 

public class Migrations : DataMigrationImpl {

        public int Create() {
            SchemaBuilder.CreateTable("BeerPartRecord", table => table.ContentPartRecord().Column("Style", DbType.String).Column("AlcoholByVolume", DbType.Single));
            return 1;
        }

        public int UpdateFrom1()
        {
            ContentDefinitionManager.AlterPartDefinition("BeerPart",
              builder => builder.Attachable());
            return 2;
        }

        public int UpdateFrom2()
        {
            ContentDefinitionManager.AlterTypeDefinition("Beer", cfg => cfg
              .WithPart("CommonPart")
              .WithPart("RoutePart")
              .WithPart("BodyPart")
              .WithPart("BeerPart")
              .WithPart("CommentsPart")
              .WithPart("TagsPart")
              .WithPart("LocalizationPart")
              .Creatable()
              .Indexed());
            return 3;
        }
}

 

I'm trying to add the field "Name", I've added the correct fields in the Model and Views for it to be displayed on the site and updated the DB with this part in the Migration.cs

 

public int UpdateFrom3()
        {
            SchemaBuilder.AlterTable("BeerPartRecord", table => table.AddColumn("Name", DbType.String));
            return 4;
        }

I can see the space for adding the field but when it successfully submits, the data in the new field isn't saved into the database. Following the debugger, I'm finding that the 

updater.TrypUpdateModel(part, Prefix, null, null)

method starts off with the "Name" field in the part being null, but returns true and having the part variable contain the "Name" field filled with the entered data. I'm unsure why the data isn't being saved to the database. Does anyone have any idea why this is happening?

Nov 21, 2011 at 4:22 PM

I've had problems before calling a column "Name" because it's a reserved keyword in SQL. Just try calling it something else like "BeerName". Your code otherwise looks all correct.

Nov 21, 2011 at 5:52 PM

Tried your suggestion, randompete. didn't work out.

Here's the newest version of my code:

Model/Beer.cs

public class BeerPartRecord : ContentPartRecord
    {
        public virtual string BeerName { get; set; }
        public virtual string Style { get; set; }
        public virtual float AlcoholByVolume { get; set; }
    }

    public class BeerPart : ContentPart<BeerPartRecord>
    {
        [Required]
        public string BeerName
        {
            get { return Record.BeerName; }
            set { Record.BeerName = value; }
        }
        [Required]
        public string Style
        {
            get { return Record.Style; }
            set { Record.Style = value; }
        }

        [Required]
        public float AlcoholByVolume
        {
            get { return Record.AlcoholByVolume; }
            set { Record.AlcoholByVolume = value; }
        }
    }

Drivers/BeerDriver.cs

 public class BeerDriver : ContentPartDriver<BeerPart>
    {
        protected override DriverResult Display(BeerPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_Beer", () => shapeHelper.Parts_Beer(Name: part.BeerName, Style: part.Style, AlcoholByVolume: part.AlcoholByVolume)); 
        }

        protected override DriverResult Editor(BeerPart part, dynamic shapeHelper)
        {
            return ContentShape("Parts_Beer_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Beer", Model: part, Prefix: Prefix));
        }

        protected override DriverResult Editor(BeerPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            bool updated = updater.TryUpdateModel(part, Prefix, null, null);
            return Editor(part, shapeHelper);
        }
    }

Migration.cs

public class Migrations : DataMigrationImpl {

        public int Create() {
            SchemaBuilder.CreateTable("BeerPartRecord", table => table.ContentPartRecord().Column("Style", DbType.String).Column("AlcoholByVolume", DbType.Single));
            return 1;
        }

        public int UpdateFrom1()
        {
            ContentDefinitionManager.AlterPartDefinition("BeerPart",
              builder => builder.Attachable());
            return 2;
        }

        public int UpdateFrom2()
        {
            ContentDefinitionManager.AlterTypeDefinition("Beer", cfg => cfg
              .WithPart("CommonPart")
              .WithPart("RoutePart")
              .WithPart("BodyPart")
              .WithPart("BeerPart")
              .WithPart("CommentsPart")
              .WithPart("TagsPart")
              .WithPart("LocalizationPart")
              .Creatable()
              .Indexed());
            return 3;
        }

        public int UpdateFrom3()
        {
            SchemaBuilder.AlterTable("BeerPartRecord", table => table.AddColumn("Name", DbType.String));
            return 4;
        }

        public int UpdateFrom4()
        {
            ContentDefinitionManager.AlterTypeDefinition("Beer", cfg => cfg.WithPart("Containable"));
            return 5;
        }

        public int UpdateFrom5()
        {
            ContentDefinitionManager.AlterPartDefinition("BeerPart", builder => builder.WithField("Name").Build());
            return 6;
        }

        public int UpdateFrom6()
        {
            SchemaBuilder.AlterTable("BeerPartRecord", table => table.DropColumn("Name"));
            return 7;
        }

        public int UpdateFrom7()
        {
            SchemaBuilder.AlterTable("BeerPartRecord", table => table.AddColumn("BeerName", DbType.String));
            return 8;
        }
    }

Any other suggestions? I'll post more code if needed.

Nov 21, 2011 at 9:17 PM

I'd like to point out that when I uploaded this Module to my testing server, the code worked perfectly, including the third field. It does not work on my local copy that I'm running through VS2010.

Coordinator
Nov 24, 2011 at 12:38 AM

You might want to zap a couple of tables, drop the migration number in the database, collapse your migration code and try again. That business with the name column may have put your system in an inconsistent state for all we know.

Nov 30, 2011 at 7:03 PM

I fixed this issue by compacting the migration code and dropping the migration number in the database. I did also have to drop some tables, but I believe that just the compacting and the dropping fixed this issue.