Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF 6.0 Migrations: ContextKey in MigrationHistory is null

I've updated to EF6 and it hasn't been fun. I have created a new migration that is just changing two fields to nullable.

public partial class AllowNullableFieldsForImage : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Scabs", "image_height", c => c.Int());
        AlterColumn("dbo.Scabs", "image_width", c => c.Int());
    }

    public override void Down()
    {
        AlterColumn("dbo.Scabs", "image_width", c => c.Int(nullable: false));
        AlterColumn("dbo.Scabs", "image_height", c => c.Int(nullable: false));
    }
}

When I run update-database I get the following error:

Cannot insert the value NULL into column 'ContextKey', table 'ScabsContext.dbo.__MigrationHistory'; column does not allow nulls. INSERT fails. The statement has been terminated.

I've found a few articles mentioning the new ContextKey field in MigrationHistory but nothing that answers my questions... Why is this field null? Is there a way (and do I need to) specify a value for ContextKey? I thought that was done automatically?

like image 208
bflemi3 Avatar asked Dec 19 '13 15:12

bflemi3


2 Answers

This looks to me like you may have been using a database for testing your migrations when you were making the change. An EF5 Migration History table has the following structure:

CREATE TABLE [dbo].[__MigrationHistory](
    [MigrationId] [nvarchar](255) NOT NULL,
    [Model] [varbinary](max) NOT NULL,
    [ProductVersion] [nvarchar](32) NOT NULL
    CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY CLUSTERED 
    ( [MigrationId] ASC )
)

When I upgraded a project from EF5 to EF6, I added an explicit migration for this purpose. If you're using decimal fields, then a migration would be necessary anyway, as it recreates these using an explicit precision anyway. When you run this first migration under EF6, it recreates the migration history table using the new structure, which looks like...

CREATE TABLE [dbo].[__MigrationHistory2] (
    [MigrationId] [nvarchar](150) NOT NULL,
    [ContextKey] [nvarchar](300) NOT NULL,
    [Model] [varbinary](max) NOT NULL,
    [ProductVersion] [nvarchar](32) NOT NULL,
    CONSTRAINT [PK_dbo.__MigrationHistory2] PRIMARY KEY ([MigrationId], [ContextKey])
)

You can see that this table includes a ContextKey field which is not null. Because of the error you're getting, I would suggest that you're trying to run a migration using EF5 on an EF6-format database.

If you want to revert your database to the EF5 format in order to run a migration from EF5, just drop the ContextKey field and recreate the primary key:

ALTER TABLE dbo.__MigrationHistory DROP CONSTRAINT [PK_dbo.__MigrationHistory2]
ALTER TABLE dbo.__MigrationHistory DROP COLUMN ContextKey
ALTER TABLE dbo.__MigrationHistory ADD CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY (MigrationId)
like image 126
Richard Avatar answered Nov 06 '22 17:11

Richard


I created the following script to update an ef5 MigrationHistory to ef6. You might want to change Migrations.Configuration to your match your namespace.

BEGIN TRANSACTION

SELECT *
INTO [tmp__MigrationHistory]
FROM [__MigrationHistory]

SELECT *
FROM [tmp__MigrationHistory]

DROP TABLE [__MigrationHistory]

CREATE TABLE [dbo].[__MigrationHistory] (
    [MigrationId] [nvarchar](150) NOT NULL
    ,[ContextKey] [nvarchar](300) NOT NULL
    ,[Model] [varbinary](max) NOT NULL
    ,[ProductVersion] [nvarchar](32) NOT NULL
    ,CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY CLUSTERED (
        [MigrationId] ASC
        ,[ContextKey] ASC
        ) WITH (
        PAD_INDEX = OFF
        ,STATISTICS_NORECOMPUTE = OFF
        ,IGNORE_DUP_KEY = OFF
        ,ALLOW_ROW_LOCKS = ON
        ,ALLOW_PAGE_LOCKS = ON
        )
    ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

INSERT INTO [__MigrationHistory] (
    [MigrationId]
    ,[ContextKey]
    ,[Model]
    ,[ProductVersion]
    )
SELECT [MigrationId]
    ,'Migrations.Configuration'
    ,[Model]
    ,[ProductVersion]
FROM [tmp__MigrationHistory]

SELECT *
FROM [__MigrationHistory]

DROP TABLE [tmp__MigrationHistory]

ROLLBACK TRANSACTION
like image 39
robkorv Avatar answered Nov 06 '22 17:11

robkorv