简体   繁体   中英

Add records using Entity Framework CF migrations

I have a table A and a table B with the following relationship:

Table A

Id
...

Table B

Id
TableA_Id  (foreign key table A)

I am using Entity Framework code first and have activated migrations.

What I want to do is to make a migration that adds a record in Table A for every exising record of Table B, and then add a foreign key reference to the new Table A row in Table B.

I have used the following command and created an empty migration:

Add-Migration <NameOfMyMigration> 

This resulted in the following code:

public partial class NameOfMyMigration : DbMigration
{
    public override void Up()
    {
        // This is where I want to write code that adds records
    }

    public override void Down()
    {
    }
}

After reading the question comments from Alexander Derck I ended up with the following solution. I'll post it here in case anyone else needs a solution to this.

However, I personally think this is more of a hack than a solution, therefore I am still interested in a proper way to solve this. Do not copy-paste this answer into your production environment without questioning its validity!

The solution is to add some code in the seed configuration. Follow this link for more info (copied from Alexander Derck's comment)

The seed code is along the lines of this:

foreach (var tableBData in context.TableB.ToList())
{
    if (tableB.TableA == null)
    {
        var tableA = new TableA();
        tableB.TableB = tableA;
    }

    context.SaveChanges();
}

Then the shady stuff: The following is an excerpt from the referenced blog entry:

[the migration seed] runs whenever the Update-Database PowerShell command is executed. Unless the Migrations initializer is being used the Migrations Seed method will not be executed when your application starts.

In order to trigger the migration (which is empty by default, ie it does not contain any actual modifications) I added the following code in my migration logic:

public partial class NameOfMyMigration : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.TableA", "DummyField", c => c.Boolean(nullable: false, defaultValue: true));
        DropColumn("dbo.TableA", "DummyField");
    }

    public override void Down()
    {
    }
}

Of course this migration is only required in case this is the last migration before a new release, because any migration following this one would also trigger the seed, thus negating the need for this.

I still feel that there must be a better way to solve this, though?

Use Automatic Migrations.

Follow the instructions from this MSDN Blog post. Automatic Migrations Walkthrough

First you need to enable the automatic migrations. In the PM console, run Enable-Migrations -EnableAutomaticMigrations

Once enabled you can use the commands Add-Migration and Update-Database to do all the heavy lifting for you.

This will scaffold your up and down methods automatically and add the records to the database.

EDIT: Updated link to current version.

I am not sure if i understand what you need, but i think your situation is that you have already Code First Project and already have database full of data and now you want to add new table so first i tried to reach out your situation :

 public class ApplicationDbContext : DbContext
    {
        public DbSet<ClassB> BList { get; set; }

        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }

    }
    public class ClassB
    {
        public ClassB()
        {
            BId = Guid.NewGuid().ToString();

        }
         [Key]
        public string BId { get; set; }


    }

and in the seed method :

protected override void Seed(ApplicationDbContext 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.BList.AddOrUpdate(

          new ClassB { BId = Guid.NewGuid().ToString() },
          new ClassB { BId = Guid.NewGuid().ToString() },
          new ClassB { BId = Guid.NewGuid().ToString() }
        );

    }

then Add-Migration and update-database now i have a table called ClassBs with 3 rows then create ClassAs Table :

public class ClassA
    {
        public ClassA()
        {
            AId = Guid.NewGuid().ToString();

        }
        [Key]
        public string AId { get; set; }


    }

and add DbSet like before to the Context:

public DbSet<ClassA> AList { get; set; }

and in the seed method :

    context.AList.AddOrUpdate(

      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() }
    );

now i have two tables with one-to-many relation just like you have finally i can now edit the ClassB table row by row . the seed method :

 protected override void Seed(ApplicationDbContext 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.
        //

        var BArray = context.BList.ToArray();
        var AArray = context.AList.ToArray();
        for (int i = 0; i < BArray.Length; i++)
        {
            if (BArray.Length == AArray.Length)
            {
                BArray[i].AID = AArray[i].AId;

            }

        }
        context.SaveChanges();
    }

now just update-database
it works .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM