Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Code First 5.0.rc Migrations doesn`t update Identity property

Say, we are using EF Code First and we have this simple model:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace EFCodeFirstIdentityProblem.Models
{
    public class CAddress
    {
        public int ID { get; set; }

        public string Street { get; set; }
        public string Building { get; set; }

        public virtual CUser User { get; set; }
    }

    public class CUser
    {
        public int ID { get; set; }

        public string Name { get; set; }
        public string Age { get; set; }

        [Required]
        public virtual CAddress Address { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<CAddress> Addresses { get; set; }
        public DbSet<CUser> Users { get; set; }
    }
}


Like this, CAddress would be principal end of this 1:0..1 relationship. Next we add connection string to Web.Config (I use MSSQL 2008 R2), make a controller that uses this model, run. EF Code First creates tables for us as expected:

enter image description hereenter image description here



So, let's assume we made a mistake, and in fact we want CUser to be principal end of this 0..1:1 relationship. So we make changes:

        ...
        [Required]
        public virtual CUser User { get; set; }
        ...

        ...
        public virtual CAddress Address { get; set; }
        ...

Build, then in Package Manager Console run and add some migration:

PM> Enable-Migrations
Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201208021053489_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.
Code First Migrations enabled for project EFCodeFirstIdentityProblem.
PM> Add-Migration ChangeDependency
Scaffolding migration 'ChangeDependency'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration 201208021157341_ChangeDependency' again.
PM> 

Here what we`ve been given for "ChangeDependency" migration:

namespace EFCodeFirstIdentityProblem.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class ChangeDependency : DbMigration
    {
        public override void Up()
        {
            DropForeignKey("dbo.CUsers", "ID", "dbo.CAddresses");
            DropIndex("dbo.CUsers", new[] { "ID" });
            AlterColumn("dbo.CAddresses", "ID", c => c.Int(nullable: false));
            AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false, identity: true)); //identity: true - this is important
            AddForeignKey("dbo.CAddresses", "ID", "dbo.CUsers", "ID");
            CreateIndex("dbo.CAddresses", "ID");
        }

        public override void Down()
        {
            DropIndex("dbo.CAddresses", new[] { "ID" });
            DropForeignKey("dbo.CAddresses", "ID", "dbo.CUsers");
            AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false));
            AlterColumn("dbo.CAddresses", "ID", c => c.Int(nullable: false, identity: true));
            CreateIndex("dbo.CUsers", "ID");
            AddForeignKey("dbo.CUsers", "ID", "dbo.CAddresses", "ID");
        }
    }
}

Importand part is:

AlterColumn("dbo.CUsers", "ID", c => c.Int(nullable: false, identity: true));

So CUsers.ID must now become Identity in DB. Let's commit this changes to DB:

PM> 
PM> Update-Database -Verbose
Using StartUp project 'EFCodeFirstIdentityProblem'.
Using NuGet project 'EFCodeFirstIdentityProblem'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'EFTest' (DataSource: (local), Provider: System.Data.SqlClient, Origin: Configuration).
Applying code-based migrations: [201208021157341_ChangeDependency].
Applying code-based migration: 201208021157341_ChangeDependency.
ALTER TABLE [dbo].[CUsers] DROP CONSTRAINT [FK_dbo.CUsers_dbo.CAddresses_ID]
DROP INDEX [IX_ID] ON [dbo].[CUsers]
ALTER TABLE [dbo].[CAddresses] ALTER COLUMN [ID] [int] NOT NULL
ALTER TABLE [dbo].[CUsers] ALTER COLUMN [ID] [int] NOT NULL
ALTER TABLE [dbo].[CAddresses] ADD CONSTRAINT [FK_dbo.CAddresses_dbo.CUsers_ID] FOREIGN KEY ([ID]) REFERENCES [dbo].[CUsers] ([ID])
CREATE INDEX [IX_ID] ON [dbo].[CAddresses]([ID])
[Inserting migration history record]
Running Seed method.
PM> 

There is no SQL instructions given by Migrations of CUsers.ID becoming Identity column in DB. So, because of this there is a problem:

(updated database) enter image description hereenter image description here

So, User is principal end now, and has to have ID Identity: "YES" flag, but Identity is still "NO". And Address is dependent end, has to have ID Identity "NO", but is still "YES". So I can't add new User to User table, because new ID is not generated for new instance.

If I drop whole database, EF Code First creates new tables from scratch properly, so this is a problem only of Migrations.

What do I do in this situation? Is this EF Migrations bug?

like image 581
Roman Avatar asked Aug 02 '12 12:08

Roman


People also ask

What does add-migration initial do?

Run the Add-Migration InitialCreate command in Package Manager Console. This creates a migration to create the existing schema. Comment out all code in the Up method of the newly created migration. This will allow us to 'apply' the migration to the local database without trying to recreate all the tables etc.


1 Answers

I'm not sure if it is a bug because there is another problem - you cannot alter existing column to identity or remove identity. I can imagine that this is considered as fully manual migration to make it clear that you must move data.

like image 156
Ladislav Mrnka Avatar answered Sep 17 '22 17:09

Ladislav Mrnka