none
BUG? - Code-First migration checks project's DB file, but writes to build's DB file RRS feed

  • Question

  • Hi there,

    During some long try and error for an issue I'm having with code migrations (find full details here) I've noticed something that seems like a bug to me:

    When I run Update-Database I always receive a pending error after the first, initial migration.
    I've even already found the reason (see thread linked above): When executing database update the migrator seems to check my project's database __MigrationHistory table, but writes only to my build's database and therefore the project's DB always stays empty and therefore I would always receive the pending error until I copy the tables from my build's DB to my project's DB manually all the time.

    Am I missing something or is this a serious bug?

    Thanks,
    Tom

    Wednesday, June 11, 2014 11:58 AM

Answers

  • Hello,

    From your description, it seems that you have two context in the same project. For this scenario, I assume that your contexts are named Sample20140604ContextA and Sample20140604ContextB. Trying below steps:

    1.enable-migrations -ContextTypeName CF.Sample20140604ContextA

    2.rename the Configuration to Sample20140604ContextA

    3.enable-migrations -ContextTypeName CF.Sample20140604ContextB

    4.rename the Configuration to Sample20140604ContextB

    5.In both generated configuaration class, add code as:

    public Sample20140604ContextA()
            {
                AutomaticMigrationsEnabled = false;
                MigrationsNamespace = "Sample20140604ContextA";
            }

    Let the two migration under different migration namespace.

    6.add-migration  -ConfigurationTypeName Sample20140604ContextA InitCreateDataBaseA

    7.add-migration  -ConfigurationTypeName Sample20140604ContextB InitCreateDataBaseB

    8.update-database -ConfigurationTypeName Sample20140604ContextA

    9.update-database -ConfigurationTypeName Sample20140604ContextB

    This will create two separate databases.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Thursday, June 12, 2014 1:23 AM
    Moderator

All replies

  • Hi there,

    I'm in the middle of following situation:

    Projects: MyLib.Client, MyLib.Server, MyLib.Model

    MyLib.Model => contains the entities
    MyLib.Client => uses the entities from MyLib.Model
    MyLib.Server => same as MyLib.Client

    Both MyLib.Server and MyLib.Client are using some different entities and some which are the same.

    My context files for server and client are both inside MyLib.Model each with a different namespace, that I also set to Configuration's property MigrationsNamespace

    When running Enable-Migrations and Add-Migration I always reference ProjectName and StartUpProjectName as MyLib.Server/MyLib.Client.

    Also I'm using two different configuration class names, that I provide with parameter -Configuration.

    Now when I run the Add-Migration command on both projects the migration files are created successfully and correctly.

    But if I try to update database it complains about an already existing table (that's the entity used by both projects).

    If I look at table __MigrationHistory I can see for my server database a ContextKey for MyLib.Client.Migrations.Configuration.

    Now two different and strange things are happening here. First this was the old name for my configuration class, but not the current one.
    Second, it seems that my MyLib.Server Migration seems to use the MyLib.Client configuration and therefore tries to add an entity twice???

    Can please someone help me out of here!? I'm totally stuck and no matter what I try I always end up with that result. Isn't it supported to have entities and context files in same assembly and migrating each context to a different project?

    Thanks for any help,
    Tom


    PS: Is it possible, that somehow my old migration tries, where the name was Configuration, was somehow cached?
    • Edited by Tom4U Tuesday, June 10, 2014 9:44 PM
    • Merged by Fred BaoModerator Thursday, June 12, 2014 2:58 AM Duplicate
    Tuesday, June 10, 2014 9:36 PM
  • Ok, something is really strange here.

    I thought I restart from scratch. So deleted all databases and migration files/folder in both projects.
    Moved my context classes to their corresponding projects and only enabled migration for my server Project.

    My final migration files looks like the following:

    namespace LRCM.Server.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;
        
        public partial class Initial : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "dbo.CoreEntityRegistry",
                    c => new
                        {
                            Id = c.Int(nullable: false, identity: true),
                            ModifiedAt = c.DateTime(nullable: false),
                        })
                    .PrimaryKey(t => t.Id);
                
                CreateTable(
                    "dbo.SrvEntityRegistry",
                    c => new
                        {
                            Id = c.Int(nullable: false, identity: true),
                            ModifiedAt = c.DateTime(nullable: false),
                            CreatedAt = c.DateTime(nullable: false),
                        })
                    .PrimaryKey(t => t.Id);
                
                CreateTable(
                    "dbo.MessageQueue",
                    c => new
                        {
                            Id = c.Int(nullable: false),
                            Target = c.Int(nullable: false),
                            Priority = c.Int(nullable: false),
                            MessageBody_MachineKey = c.String(),
                            MessageBody_Message = c.String(),
                            MessageBody_Module = c.String(),
                        })
                    .PrimaryKey(t => t.Id)
                    .ForeignKey("dbo.CoreEntityRegistry", t => t.Id)
                    .Index(t => t.Id);
                
                CreateTable(
                    "dbo.Registrations",
                    c => new
                        {
                            Id = c.Int(nullable: false),
                            ClientId = c.Int(nullable: false),
                            CertRequest = c.String(),
                            RequestId = c.Int(nullable: false),
                            Certificate = c.String(),
                            State = c.String(),
                        })
                    .PrimaryKey(t => t.Id)
                    .ForeignKey("dbo.SrvEntityRegistry", t => t.Id)
                    .ForeignKey("dbo.Clients", t => t.ClientId)
                    .Index(t => t.Id)
                    .Index(t => t.ClientId);
                
                CreateTable(
                    "dbo.Clients",
                    c => new
                        {
                            Id = c.Int(nullable: false),
                            Guid = c.Guid(nullable: false),
                            MachineKey = c.String(nullable: false),
                            IsOnline = c.Boolean(nullable: false),
                        })
                    .PrimaryKey(t => t.Id)
                    .ForeignKey("dbo.SrvEntityRegistry", t => t.Id)
                    .Index(t => t.Id)
                    .Index(t => t.Guid, unique: true);
                
            }
            
            public override void Down()
            {
                DropForeignKey("dbo.Clients", "Id", "dbo.SrvEntityRegistry");
                DropForeignKey("dbo.Registrations", "ClientId", "dbo.Clients");
                DropForeignKey("dbo.Registrations", "Id", "dbo.SrvEntityRegistry");
                DropForeignKey("dbo.MessageQueue", "Id", "dbo.CoreEntityRegistry");
                DropIndex("dbo.Clients", new[] { "Guid" });
                DropIndex("dbo.Clients", new[] { "Id" });
                DropIndex("dbo.Registrations", new[] { "ClientId" });
                DropIndex("dbo.Registrations", new[] { "Id" });
                DropIndex("dbo.MessageQueue", new[] { "Id" });
                DropTable("dbo.Clients");
                DropTable("dbo.Registrations");
                DropTable("dbo.MessageQueue");
                DropTable("dbo.SrvEntityRegistry");
                DropTable("dbo.CoreEntityRegistry");
            }
        }
    }

    And my context class like the following:

    using LRCM.Model.Contracts;
    using System.Data.Entity;
    
    namespace LRCM.Server.Data
    {
        public partial class LRCMServerContext : DbContext
        {
            public LRCMServerContext()
                : base("LRCMServerContext")
            {
                //Database.SetInitializer<LRCMServerContext>(new CreateDatabaseIfNotExists<LRCMServerContext>());
                Database.SetInitializer<LRCMServerContext>(new DropCreateDatabaseIfModelChanges<LRCMServerContext>());
            }
    
            public DbSet<LRCMSrvEntity> SrvEntities { get; set; }
    
            public DbSet<LRCMCoreEntity> CoreEntities { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        }
    }

    But in __MigrationHistory it still references LRCM.Client.Migrations.Configuration although there isn't event a physical file anymore in my whole solution containing any other migration configuration class.

    So where is this coming from? Is it a bug?

    Wednesday, June 11, 2014 8:24 AM
  • Sorry for double posting, but I thought I cannot change the title and therefore opened another question with the final reason and question: http://social.msdn.microsoft.com/Forums/en-US/114cada9-7ad7-4789-ac2f-769ac2c69dd0/bug-codefirst-migration-checks-projects-db-file-but-writes-to-builds-db-file?forum=adodotnetentityframework

    Could some friendly moderator please be so kind and close this question!?

    Wednesday, June 11, 2014 12:01 PM
  • Hello,

    From your description, it seems that you have two context in the same project. For this scenario, I assume that your contexts are named Sample20140604ContextA and Sample20140604ContextB. Trying below steps:

    1.enable-migrations -ContextTypeName CF.Sample20140604ContextA

    2.rename the Configuration to Sample20140604ContextA

    3.enable-migrations -ContextTypeName CF.Sample20140604ContextB

    4.rename the Configuration to Sample20140604ContextB

    5.In both generated configuaration class, add code as:

    public Sample20140604ContextA()
            {
                AutomaticMigrationsEnabled = false;
                MigrationsNamespace = "Sample20140604ContextA";
            }

    Let the two migration under different migration namespace.

    6.add-migration  -ConfigurationTypeName Sample20140604ContextA InitCreateDataBaseA

    7.add-migration  -ConfigurationTypeName Sample20140604ContextB InitCreateDataBaseB

    8.update-database -ConfigurationTypeName Sample20140604ContextA

    9.update-database -ConfigurationTypeName Sample20140604ContextB

    This will create two separate databases.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Thursday, June 12, 2014 1:23 AM
    Moderator