dotnetIntelligency

Saturday, December 31, 2016

E.F Code first migrations

Entity Framework Code First Migrations
Here are a few options you have when modeling your entities for an enterprise web application:
  • Database First: This involves generating an EDMX file from your database. Every time your tables and fields change, you’ll have to update the model from Visual Studio.
  • Model First: You may use Visual Studio to create your database model and relationships between entities. I wouldn’t normally recommend this for an Agile/Scrum project.
  • Code First with automatic migrations: You can enable Migrations and configure it to “Enable Automatic Migrations”.
  • Code First with manual migrations: In this blog post, I will focus on Migrations with manual updates.

What is Migrations History Table?

Migrations history table is a table used by Code First Migrations to store details about migrations applied to the database. By default the name of the table in the database is __MigrationHistory and it is created when applying the first migration do the database. In Entity Framework 5 this table was a system table if the application used Microsoft Sql Server database. This has changed in Entity Framework 6 however and the migrations history table is no longer marked a system table.

Why customize Migrations History Table?

Migrations history table is supposed to be used solely by Code First Migrations and changing it manually can break migrations. However sometimes the default configuration is not suitable and the table needs to be customized, for instance:
  • You need to change names and/or facets of the columns to enable a 3rd party Migrations provider
  • You want to change the name of the table
  • You need to use a non-default schema for the __MigrationHistory table
  • You need to store additional data for a given version of the context and therefore you need to add an additional column to the table
How to customize Migrations History Table?
Before you start you need to know that you can customize the migrations history table only before you apply the first migration. Now, to the code.

First, you will need to create a class derived from System.Data.Entity.Migrations.History.HistoryContext class. The HistoryContext class is derived from the DbContext class so configuring the migrations history table is very similar to configuring EF models with fluent API. You just need to override the OnModelCreating method and use fluent API to configure the table.

Note: Typically when you configure EF models you don’t need to call base.OnModelCreating() from the overridden OnModelCreating method since the DbContext.OnModelCreating() has empty body. This is not the case when configuring the migrations history table. In this case the first thing to do in your OnModelCreating() override is to actually call base.OnModelCreating(). This will configure the migrations history table in the default way which you then tweak in the overriding method.

Let’s say you want to rename the migrations history table and put it to a custom schema called “admin”. In addition your DBA would like you to rename the MigrationId column to Migration_ID. You could achieve this by creating the following class derived from HistoryContext:

    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Migrations.History;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class MyHistoryContext : HistoryContext
        {
            public MyHistoryContext(DbConnection dbConnection, string
              defaultSchema)
                : base(dbConnection, defaultSchema)
            {
            }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Entity<HistoryRow>().ToTable(tableName:
                     "MigrationHistory", schemaName: "admin");
                modelBuilder.Entity<HistoryRow>().Property(p =>
                     p.MigrationId).HasColumnName("Migration_ID");
            }
        }
    }

Once your custom HistoryContext is ready you need to make EF aware of it by registering it via code-based configuration:
using System.Data.Entity;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class ModelConfiguration : DbConfiguration
        {
            public ModelConfiguration()
            {
                this.SetHistoryContext("System.Data.SqlClient",
                    (connection, defaultSchema) => new
                       MyHistoryContext(connection, defaultSchema));
            }
        }
    }

That’s pretty much it. Now you can go to the Package Manager Console, Enable-Migrations, Add-Migration and finally Update-Database. This should result in adding to the database a migrations history table configured according to the details you specified in your HistoryContext derived class.




No comments:

Post a Comment