EF 不会根据我的模型更新表

EF won't update tables based on my model

起初我创建了一个只包含基本属性的 Person 模型:

[Table("SGDB_Persons")]
public class Person {
    public int Id { get; set; }

    [Required]
    public string Firstname { get; set; }

    [Required]
    public string Lastname { get; set; }

    [Required]
    public Department Department { get; set; }

    [Required]
    public SourceType SourceType { get; set; }

在我发现我遗漏了一些东西后,我添加了一个新的 PersonData 属性:

[Required]
    public PersonData PersonData { get; set; }

不幸的是,EF 根本不会更新数据库 - 最初包含 Person 类型对象的 PersonData 已更新,因此不再有 Person 属性。另一方面,EF 不会为 PersonData_Id.

创建新列

此外,ID 列不会自动递增(所有其他 table 的 Id 列都会自动递增)。令我困惑的是以下在我的 Person table:

中创建的 Constraing

CONSTRAINT [FK_dbo.SGDB_Persons_dbo.SGDB_PersonData_Id] FOREIGN KEY ([Id]) REFERENCES [dbo].[SGDB_PersonData] ([Id])

我什么都试过了(至少我是这么认为的)。我手动删除了所有 tables / 整个数据库,重新安装了 EF,执行了手动迁移,但似乎没有任何效果。

我认为是这个问题导致我无法使用以下代码为我的数据库播种:

protected override void Seed(PersonContext context) {
        base.Seed(context);
        var dep = new DepartmentContext().Departments.First();

        var status = new Status("Test");
        var persondata = new PersonData(status);
        context.Status.Add(status);
        context.PersonData.Add(persondata);
        for (int i = 0; i < 10; i++) {
            var person = new Person {
                Firstname = $"TestPersonFirstname{i}",
                Lastname = $"TestPersonLastname{i}",
                SourceType = COM.SourceType.Manual,
                Department = dep,
                PersonData = persondata
            };
            context.Persons.Add(person);
        }
        context.SaveChanges();
    }

每次执行此代码时,我都会收到异常:

The member with identity 'SGDB.DAL.Contexts.Person_Department' does not exist in the metadata collection. Parameter name: identity.

我不知道这两个问题是否与同一个问题有关,但都需要解决:)

提前致谢!

更新 1

我的解决方案分为几个不同的项目:

BLL、DAL、COM、UI

DataContexts 位于 DAL 项目中,模型位于 COM 项目中。

部门模型:

[Table("SGDB_Departments")]
public class Department {
    public int Id { get; set; }

    [Required]
    public string Costcenter { get; set; }

    [Required]
    public string Abbreviation { get; set; }

    public string Description { get; set; }

    public string FullDepartmentName {
        get {
            return $@"{Division.Abbreviation}\{Abbreviation}";
        }
    }
    [Required]
    public virtual Division Division { get; set; }
}

个人数据模型:

[Table("SGDB_PersonData")]
public class PersonData {
    public PersonData(Status status) {
        Status = status;
    }

    public int Id { get; set; }
    public DateTime Limit { get; set; }
    public Person Responsible { get; set; }
    [Required]
    public Status Status { get; set; }
}

人 table(如您所见)有一个 Department_Id 列(EF 自动插入)。

澄清

Person 对象包含一个 PersonData 对象作为此 Person 的附加信息。一个人可能/可能没有一个负责人(所以 PersonData.Responsible 不是父人的导航 属性)。 另外,如果可能的话,我不想在 PersonData table.

中有一个外键

据我所知,我必须修改

modelBuilder.Entity<Person>()
       .HasRequired(e => e.PersonData)
       .WithRequiredPrincipal(e => e.Responsible)
       .WillCascadeOnDelete(true);

modelBuilder.Entity<Person>()
       .HasRequired(e => e.PersonData)
       .WithMany()
       .WillCascadeOnDelete(true);

我会试试这个,如果它解决了我的问题,我会报告。

更新 2

The member with identity 'SGDB.DAL.Contexts.Person_Department' does not exist in the metadata collection.

您的模型定义了 PersonPersonData 之间的 one-to-one 关系,后者是必需的,前者是可选的。 EF 始终将 one-to-one 关系的必需部分用作 principal,并将可选部分用作 dependent。因此它认为 PersonaData 是主体,Person - 依赖并反映在数据库 table 设计中。

你需要相反的,而且双方都需要。当两侧都是必需或可选时,EF 无法自动派生 principal/dependent 侧并且无法通过数据注释(属性)指定它,因此您需要一个流畅的 API 设置。

覆盖您的 DbContext OnModelCreating 并添加如下内容:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()               
        .HasRequired(e => e.PersonData)
        .WithRequiredPrincipal(e => e.Responsible)
        .WillCascadeOnDelete(true);

    base.OnModelCreating(modelBuilder);
}

它的作用是告诉EF,Person->PersonData关系的两边都是必须的,Person是主体。这应该再次使您的 Person.Id 列自动递增,并且应该解决问题的人员数据部分。

我注意到的另一件事是这一行:

var dep = new DepartmentContext().Departments.First();

而同一过程的所有其他部分都使用名为 context 的变量。这个 might/might 不是问题,检查一下就可以了。

更新: 从更新问题中的说明可以看出,Person 和 [=] 之间有 两个 关系15=],所以你需要像这样为它们中的每一个单独配置:

modelBuilder.Entity<Person>()
    .HasRequired(e => e.PersonData)
    .WithRequiredPrincipal()
    .WillCascadeOnDelete(true);

modelBuilder.Entity<PersonData>()
    .HasOptional(e => e.Responsible)
    .WithOptionalDependent() // or WithMany()
    .WillCascadeOnDelete(false);

请注意,在 PersonData table 中没有办法不引入额外的 FK 列。它需要表示 Responsible 关系,因此您最终会得到一个名为 Responsible_Id.

的 table 列