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

C# 使用实体框架CF迁移添加记录,c#,.net,entity-framework,entity-framework-migrations,C#,.net,Entity Framework,Entity Framework Migrations,我的表a和表B具有以下关系: 表A Id ... 表B Id TableA_Id (foreign key table A) 我首先使用实体框架代码并激活了迁移 我想做的是进行迁移,在表a中为表B的每个现有记录添加一条记录,然后在表B中的新表a行中添加一个外键引用。 我使用了以下命令并创建了一个空迁移: Add-Migration <NameOfMyMigration> 在阅读了Alexander Derck的问题评论后,我得出了以下解决方案。我会把它贴在这里,以防其他人需

我的表a和表B具有以下关系:

表A

Id
...
表B

Id
TableA_Id  (foreign key table A)
我首先使用实体框架代码并激活了迁移

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

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

Add-Migration <NameOfMyMigration> 

在阅读了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控制台中,运行
启用迁移-EnableAutomaticMigrations

启用后,您可以使用命令
添加迁移
更新数据库
来完成所有繁重的工作

这将自动构建up和down方法,并将记录添加到数据库中


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

我不确定是否理解您的需要,但我认为您的情况是,您已经编写了第一个项目的代码,并且数据库中已经充满了数据,现在您想添加新表,因此首先我尝试了解您的情况:

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


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

public DbSet<ClassA> AList { get; set; }
现在我有两个表,和你们一样有一对多的关系 最后,我现在可以逐行编辑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.
        //
        context.BList.AddOrUpdate(

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

    }
    context.AList.AddOrUpdate(

      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() }
    );
 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();
    }
受保护的重写无效种子(ApplicationDbContext上下文)
{
//迁移到最新版本后将调用此方法。
//您可以使用DbSet.AddOrUpdate()助手扩展方法
//避免创建重复的种子数据。
//
var BArray=context.BList.ToArray();
var AArray=context.AList.ToArray();
for(int i=0;i
现在只需更新数据库

它是有效的。

在过去的好日子里,类似的事情可以通过触发器来完成。只是说(您可以从迁移配置类中种子)谢谢!我在seed类中添加了一些代码,可以根据需要添加记录。然而,为了让迁移触发seed逻辑,我必须使Up方法添加并删除一个伪列,否则seed代码将无法运行。我觉得这不是一个很棒的解决方案。。。有没有更好的方法来实现这一点?:)虽然正确,但问题中明确指出迁移已经设置,并且我确实运行了Add Migration命令来创建空迁移(因为没有涉及模型更改)。是的,但是“手动”迁移和自动迁移之间存在差异。启用自动迁移以能够使用此解决方案。我看不出自动迁移如何帮助我使用新的dataHi@havardhu更新现有表。我重新阅读了您的问题,我相信您是在问如何在TableA中自动添加表B中具有遗忘键的行。这是否正确?不,两个表都已经存在,它们之间的关系也是如此。唯一新的是,现在表a中必须有一个相关行,这以前不是一个要求。因此,我需要一种在不引入任何模型更改的情况下为数据播种的正确方法。我找到了一个解决方案(见我自己的答案),但它更像是一个黑客,而不是我书中的一个合适的解决方案。你不需要对种子数据进行任何模型更改。你只需要在种子方法中编写代码,然后执行更新数据库即可。
    context.AList.AddOrUpdate(

      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() },
      new ClassA { AId = Guid.NewGuid().ToString() }
    );
 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();
    }