IT:AD:Code First:CodeMigration

Summary

Note: An interesting thing to note is that this is the first time I've noticed MS using the Package Manager Console for far more that Packaging. They're using it as a completely new way to script up VS operations. Worth Keeping an eye on future developments in this direction.

Elevated Rights

To do code migrations, the application will need elevated db rights.

Without that, you'll have to use the -script switch to collect together the partial scripts.

Install EntityFramework using Nuget

On the Dev machine, same as always:

  • In the Nuget/Package Manager Console, type: Install-Package EntityFramework
  • Write code: entities and dbContexts.
  • Run it the first time, and it creates a Database based on the connection string given.

Enable Migrations In the Project

In Nuget/Package Manager Console, type:

Enable-Migrations 
//Default is same as being verbose regarding EnableAutomaticMigrations:
Enable-Migrations -EnableAutomaticMigrations=false    

The Powershell script creates a new Migrations folder in the Visual studio project, containing a single Configuration class file:

namespace XAct.Spikes.CodeMigration.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    //Note: it's sealed, so has to be in same assembly as...context?
    internal sealed class Configuration : DbMigrationsConfiguration<XAct.Spikes.CodeMigration.MyContext>
    {
        public Configuration()
        {
            //Value set by flag when `Enable-Migrations` was invoked:
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(XAct.Spikes.CodeMigration.MyContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}

  • Enable-Migrations: Enables Code First Migrations in a project (already covered).
  • Add-Migration: Scaffolds a migration script for any pending model changes. MS also refers to this as Code Migration.
  • Update-Database: Applies any pending migrations to the database.
  • Get-Migrations: Displays the migrations that have been applied to the target database. MS also refers to this as Automatic Migration.

Get help:

get-help command-name -detailed
//eg:
get-help Update-Database -detailed
The easiest command to get to know first is the `Update-Database` command -- but note that for professional reasons you'll definitely want to use `Add-Migration` once you get going.

It's easy because all you have to do is:

  • Make changes to an Entity
  • Try to run
  • Get the exception that says the Model has changes
  • Use this command to automatically calculate and push the changes to our model to the database.

    Update-Database -verbose

The Db will automatically be updated (hence why MS refers to it as Automatic Migration).

Nice and easy… but it really is too easy for pro work.

So…if Update-Database -verbose is too easy, what's the solution?

The solution MS is pushing is to be more … careful.

  • Make changes to an Entity
  • Try to run
  • Get the exception that says the Model has changes
  • This time, instead of calling -Update-Database, call Add-Migration:

    Add-Migration {MyUniqueName}

This creates a new file in the Migrations folder, outlining the shape of the same entity, but with the added property.

This is referred to by MS as a Coded Migration.

Note:

  • File name has date prefix to provide processing order
  • Class that enherits from DbMigration

Note:
Given the limitations of automatic migrations we recommend using code-based migrations in team environments.
Src: MS: http://msdn.microsoft.com/en-US/data/jj554735

namespace XAct.Spikes.CodeMigration.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddEstimateDescription : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Estimates",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        Name = c.String(nullable: false, maxLength: 50),
                        Amount = c.Double(nullable: false),
                        Description = c.String(),
                    })
                .PrimaryKey(t => t.Id);
            
        }
        
        public override void Down()
        {
            DropTable("dbo.Estimates");
        }
    }
}

One of the options we have now is to update the Db – using the original 'Update-Database -verbose command. ### Scripting Changes But...that's nice...but how do we translate all these little updates into something we can deploy as an update script in an client environment which will never give admin rights to the application's account? That's stumping me. For now, I've found that one can use the -script` flag to output Sql to Visual Studio.

Update-Database -script

CREATE TABLE [dbo].[Estimates] (
    [Id] [int] NOT NULL IDENTITY,
    [Name] [nvarchar](50) NOT NULL,
    [Amount] [float] NOT NULL,
    [Description] [nvarchar](max),
    CONSTRAINT [PK_dbo.Estimates] PRIMARY KEY ([Id])
)
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES ('201302041024147_AddEstimateDescription', 'XAct.Spikes.CodeMigration.Migrations.Configuration', 0x1F8B0800000000000400CD59CD72DB3610BE77A6EFC0E1A93D8490E438693D54328A64379E5676C67432BD652072256342022C01BAD2B3F5D047EA2B74C13FF157A464BBD38B470281DD6F17BBFBF193FFF9EB6FFBFD36F08D478824137C6A8EAD9169007785C7F8666AC66AFDEA27F3FDBBEFBFB32FBD606B7CC9F79DE97D7892CBA9F9A054784188741F20A0D20A981B0929D6CA724540A827C86434FA998CC704D08489B60CC3BE8BB96201245FF0EB5C70174215537F293CF065B68E4F9CC4AA714303902175616AFE3E7395E584EC1B486B8EBB976C135185A84C63E6338A801CF0D7A611BEBEF82CC15191E01B27C41DD4BFDF8580CFD7D49790C1BF085F0F8D6034D11110CAB95099C313326016B16174979805B5D3B09208A7E6A5C4B45005E55DB8EF57D8551670E953244288D4EE0ED6D9D96BCF3448F51CA91F2C8E95CE68F7F889ABB38969DCC4BE4F573E1459C2343A4A44F00B70C03C83F7892A0511D7672181DFF05AF3A1FFE65EF03AB0B04C6349B7BF01DFA887A9798E9574C5B6E0E50B99E3CF9C6119E21915C5D002ECB0D35920B0C472B70B11E3D1A38D2C40BA110BD3BBEE0C003F0E8AA0ECCB26FBAB6F1604B683A20CF39DE158262BB055B5B248773BA06AD5234D636F3EED07ABA8AC7ACC75231F99C4FBDEB598C89EDC893FB12CDE5E5C4B67271504797C593FBD1DD40FE309198F927E0AF2FE95ED292A9271B0712AD8DE74617B733AB64643B6B8E9EFD16258E9C66BC149FA4D64A580080658E89F0015449D353E393F3FAD4BFB11D6F094C3EB9E19E3C97F0427E1A31CC907C6A9EE8C21CDFF74D7F8D58B5D9571EE816C9CBD4C325A67944D5246CE999B7450B7BDA46188404B549EAD184ECAE3F357CEF1041AA436882B5B78B4981485271C097403B5A7BAC63CB86291540BAAE88AEA5CCCBDA0B1AD77ECE67EEAD3B7DEC4FB3CE627F4E7F454E7EB8CD5FE2E504EE5154617200927814201ABEB35223BECB8D4A751CB8BC05CF871C0BB5E260E9D4E29BE7C3E5D196E21E7EBB28D7C6DB8950A61974D551E34EDD9A496D1FA0D92C615D6C66CBD2606554C41B52FCF583D5598FAB6743F58E93EAB28449913BF7598648F2FD323ED75DD7A85C2CAB77E2CDB76BB28B352D9C351647C308694672AE8D3A52799AD7348D97EFDD920472FDA298D57BEFA96C27B413F359AB1B391DF2F231B1C906E310D4CCB23F3F4FC2F3785F3873FF719E871946F5852CED620D5BDF80628877417D624E809F29048E9F9FF578DC874F8BD6AF04891559687FC9146EE038D1A02F149EA6FED0BAA9E43FCE5F07E08E8F6C7B2C1A70ABCE60BC930A17750E7A5053D35BD95C00052A02585384C0626B3F9A0126C73F3F56B317A5F96E39E4B319E77613B7F56C5D87073AC626CE23C5631F659384931B6F66DA2199BA2A31740AF206C9F12E3D65FAF8EF556D17BE8679548BE46C39F6ABE5DD3B506D4FE6BDC6187C3245B93236D52FE41D6C6D1C736FBFED13FCF7270F595EF8DE67BAEF95AE441E2F42883C9B7D4530C8A7A38E76691626BEA2A7CEC829489AAFD42FD588FA96005DE35BF8D5518AB999410ACFCCAEF8C3639EC3FD1A555CCF66D32CBE573848030198600B7FC43CC7CAFC07DD524962E137AE4672C8AA850D5A3B9CDAEB07423F8404359FA161002D71C7C0F41E8EB117FCB1DFA08DDD8FA7358CD98BD60143B3F90998DFD79FDFF01A2FF41F0EE5F0738356C52180000, '6.0.0-alpha2-11210')

But, as you can imagine, running this in Sql will give:

Msg 2714, Level 16, State 6, Line 1
There is already an object named 'Estimates' in the database.

Solution as per (http://stackoverflow.com/questions/13238203/automatic-migrations-for-asp-net-simplemembershipprovider) is:

Add-Migration InitialMigrations -IgnoreChanges
  • /home/skysigal/public_html/data/pages/it/ad/code_first/codemigration.txt
  • Last modified: 2023/11/04 03:22
  • by 127.0.0.1