Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Feb 22, 2019 @ 08:30
    Matt Brailsford
    1

    DTO based Schema Migration Considerations

    Within Umbraco there are some really handy tools for creating tables from DTO object definitions, saving you having to explicitly define your DB table structures.

    public class MyModel {
        public int Prop1 { get; set; }
        public int Prop2 { get; set; }
        public int Prop3 { get; set; }
    }
    

    _

    ...
    Create.Table<MyModel>().Do();
    ...
    

    These all work fine, until we start to think about migrations.

    Lets say we are creating a new product, so our initial Migration will be to create our DB tables. For ease, we'll use the handy extensions that let you pass it a DTO object and create the table for you based on the object definition. Great, perfect, we have a DB table.

    Now lets say we want to pre-populate that DB table with some data, so we create a new migration and do a bunch of insert statements to send the data through. Great, perfect, we now have data in our DB table.

    db.Execute($"INSERT myModel (prop1, prop2, prop3) VALUES (1, 2, 3);");
    

    Now, lets say a couple months down the road, we decide one of the properties on our object is no longer needed and so update our DTO and create a migration step to remove the column. Great, perfect, for anyone now upgrading the column will be removed and they will be in the desired state.

    public class MyModel {
        public int Prop1 { get; set; }
        public int Prop2 { get; set; }
    }
    

    _

    ...
    Delete.Column("Prop3").FromTable("myModel").Do();
    ...
    

    However, we now have a problem because we've modified our DTO, this has effectively changed our original create db tables migration such that anyone installing a fresh will already be in the state where the removed property is not there. Now, migration 2 will fail because a column it expects to be there is no longer there.

    Ultimately, by using this approach it can bring in inconsistencies between migrations, such that we can no longer predict the previous state of the system.

    One approach would be to say not use the object type based DB creation methods and instead explicitly define your Schema like https://github.com/umbraco/Umbraco-CMS/blob/dev-v8/src/Umbraco.Core/Migrations/Upgrade/V80_0/AddContentNuTable.cs, however this is a bit more complex.

    Create.Table("myModel")
      .WithColumn("Prop1").AsInt32().NotNullable()
      .WithColumn("Prop2").AsInt32().NotNullable()
      .WithColumn("Prop3").AsInt32().NotNullable()
      .Do();
    

    The question then is can this be made to work in some way? Or should we be discouraging / removing the ability to create tables from an object type definition because it's just not scalable?

    For reference, this discussion originated on twitter here https://twitter.com/mattbrailsford/status/1098669770809987077

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    Feb 22, 2019 @ 08:51
    Morten Bock
    2

    If we take a look at Entity Framework, they have a similar feature for create a DB schema from a model. They do also support detecting differences between the current DB schema, and the model, and then only apply the changes.

    However, that feature is not recommended for use in production, and is mostly a tool for rapid development.

    I would argue that using DTO's in migrations is not production code, exactly for the reasons you mention. The DTO is not part of the migration, and as such, will change over time.

    A migration should basically never change, and thus should not have dependencies to anything else.

  • Søren Gregersen 441 posts 1884 karma points MVP 2x c-trib
    Feb 22, 2019 @ 10:53
    Søren Gregersen
    0

    so in short: Create.Table<MyModel>().Do(); is only for dev?

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    Feb 22, 2019 @ 12:50
    Morten Bock
    1

    In my opinion, yes. Or remove it all together.

Please Sign in or register to post replies

Write your reply to:

Draft