如何更改将现有数据保留在 entity framework 代码中的关系?

How to alter relationship keeping existing data in entity framework code first?

我有两个实体

public class Account
    {
        [Key]
        public int Id { get; set;
        public int MemberInfoId { get; set; }
        public Member MemberInfo { get; set; }
        //Other Properties
    }

public class Member
    {
        [Key]
        public int Id { get; set; }
        //Other Properties
    }

有以下关系

modelBuilder.Entity<Account>()
                .HasRequired(a => a.MemberInfo)
                .WithMany()
                .HasForeignKey(a => a.MemberInfoId)
                .WillCascadeOnDelete(true);

但是,一个帐户只有一个成员,所以下面的关系更适合(我猜)

modelBuilder.Entity<Account>()
                .HasRequired(a => a.MemberInfo)
                .WithRequiredPrincipal()
                .WillCascadeOnDelete(true);

但是代码优先迁移不会迁移到那个。它给出了以下错误

The object 'PK_dbo.Members' is dependent on column 'Id'.
The object 'FK_dbo.Accounts_dbo.Members_MemberInfo_Id' is dependent on column 'Id'.
ALTER TABLE DROP COLUMN Id failed because one or more objects access this column.

如何在不重新创建数据库以保留已插入的数据的情况下更改关系?

首先,您可以阅读 this page 关于将基于代码的迁移与自动迁移混合使用的内容,看看您是否一开始就想走这条路。一般来说,如果你有一个团队参与,这不是一个好主意。

接下来,如果您将 MemberAccount 之间的关系更改为一对一关系,则 Entity Framework 需要主键依赖方也是外键。曾经作为依赖端主键的列,从 EF 的角度来看将变得无用。您也将不再需要 Account.MemberInfoId

最后创建迁移, 完成模型修改后,您可以运行 Add-Migration 使用迁移名称。这将创建一个带有 DbMigration class 的迁移文件,您可以修改该文件。您可能需要执行以下操作:

  • Member 中创建一个新列来保存新的外键
  • 使用 Sql() 使用关联帐户的主键更新该列中的值
  • 删除外键约束、索引和主键
  • 删除 account.memberinfo_id 列和 member.id 列(这是可选的,但如果您不删除 member.id 列,则必须确保映射模型的 Member.Id 属性 到上面创建的列)。
  • 将成员中的新列重命名为 id
  • 将主键添加到 Member
  • 中的新列
  • 添加索引和外键

我确定我错过了一些东西,但这是一般要点。我可能还会备份所有内容,因为前五次左右肯定会出错。