使用实体框架CF迁移添加记录

本文关键字:迁移 添加 加记录 CF 框架 实体 | 更新日期: 2023-09-27 18:28:27

我有一个表a和一个表B,具有以下关系:

表A

Id
...

表B

Id
TableA_Id  (foreign key table A)

我首先使用实体框架代码,并已激活迁移。

我想做的是进行迁移,为表B的每个现有记录在表a中添加一条记录,然后向表B中的新表a行添加外键引用。

我使用了以下命令并创建了一个空迁移:

Add-Migration <NameOfMyMigration> 

这导致了以下代码:

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

使用实体框架CF迁移添加记录

我不确定我是否理解你的需求,但我认为你的情况是,你已经有了代码优先项目,并且已经有了充满数据的数据库,现在你想添加新的表,所以首先我试图了解你的情况:

 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; }

    }

种子法:

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() }
        );
    }

然后添加迁移并更新数据库现在我有一个名为ClassB的表,它有3行然后创建ClassAs表:

public class ClassA
    {
        public ClassA()
        {
            AId = Guid.NewGuid().ToString();
        }
        [Key]
        public string AId { get; set; }

    }

并像以前一样将DbSet添加到上下文中:

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

种子法:

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

现在我有两张和你一样有一对多关系的桌子最后,我可以逐行编辑ClassB表了。种子法:

 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();
    }

现在只更新数据库
它是有效的。

在阅读了Alexander Derck的问题评论后,我得出了以下解决方案。我会把它贴在这里,以防其他人需要解决这个问题。

然而,我个人认为这更多的是一个破解而非解决方案,因此我仍然对解决这个问题的正确方法感兴趣。不要在不质疑其有效性的情况下将此答案复制粘贴到您的生产环境中

解决方案是在种子配置中添加一些代码。点击此链接获取更多信息(复制自Alexander Derck的评论)

种子代码如下:

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

然后是阴暗的东西:以下是引用的博客文章的摘录:

只要执行更新数据库PowerShell命令,就会运行[迁移种子]。除非使用迁移初始值设定项,否则迁移种子方法将不会在应用程序启动时执行。

为了触发迁移(默认情况下为空,即不包含任何实际修改),我在迁移逻辑中添加了以下代码:

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()
    {
    }
}

当然,只有当这是新版本之前的最后一次迁移时,才需要进行此迁移,因为此迁移之后的任何迁移都会触发种子,因此不需要执行此迁移。

不过,我仍然觉得必须有更好的方法来解决这个问题?

使用自动迁移。

请按照MSDN博客中的说明进行操作。自动迁移漫游

首先,您需要启用自动迁移。在PM控制台中,运行Enable-Migrations -EnableAutomaticMigrations

启用后,您可以使用命令Add-MigrationUpdate-Database为您完成所有繁重的工作。

这将自动构建向上和向下方法,并将记录添加到数据库中。

编辑:更新到当前版本的链接。