首先,我创建了一个仅包含基本属性的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列不会自动递增(所有其他表的Id列都可以)。令我困惑的是下面的Constraing在我的Person表中创建:
CONSTRAINT [FK_dbo.SGDB_Persons_dbo.SGDB_PersonData_Id] FOREIGN KEY([Id])REFERENCES [dbo]。[SGDB_PersonData]([Id])
我尝试了一切(至少我是这么认为的)。我手动删除了所有表/整个数据库,重新安装了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();
}
每次执行此代码时,我都会遇到异常:
元数据集合中不存在具有标识“SGDB.DAL.Contexts.Person_Department”的成员。参数名称: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; }
}
PersonData Model:
[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; }
}
Person表(如你所见)有一个Department_Id列(EF自动插入)。
澄清
Person对象包含PersonData对象,作为此Person的附加信息。一个人可能/可能没有负责人(因此PersonData.Responsible不是父人的导航属性)。 另外,如果可能的话,我不希望在PersonData表中有一个外键。
我发现我必须修改
modelBuilder.Entity<Person>()
.HasRequired(e => e.PersonData)
.WithRequiredPrincipal(e => e.Responsible)
.WillCascadeOnDelete(true);
到
modelBuilder.Entity<Person>()
.HasRequired(e => e.PersonData)
.WithMany()
.WillCascadeOnDelete(true);
如果它解决了我的问题,我会尝试并报告。
更新2
元数据集合中不存在具有标识“SGDB.DAL.Contexts.Person_Department”的成员。
答案 0 :(得分:1)
您的模型定义one-to-one
和Person
之间的PersonData
关系,以后需要和前者 - 可选。 EF始终将one-to-one
关系的所需部分用作主体,将可选部分用作依赖。因此,它认为PersonaData
是主体,Person
- 依赖,并在数据库表设计中反映出来。
你需要相反的,双方都需要 。当双方都是必需的或可选的时,EF不能自动派生主要/从属方,并且无法通过数据注释(属性)指定,因此您需要一个流畅的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
的变量。这可能/可能不是问题,只需检查出来。
更新:根据更新后问题的说明,您发现Person
和PersonData
之间存在两个关系,因此您需要单独处理他们每个人的配置如下:
modelBuilder.Entity<Person>()
.HasRequired(e => e.PersonData)
.WithRequiredPrincipal()
.WillCascadeOnDelete(true);
modelBuilder.Entity<PersonData>()
.HasOptional(e => e.Responsible)
.WithOptionalDependent() // or WithMany()
.WillCascadeOnDelete(false);
请注意,PersonData
表中无法引入其他FK列。需要表示Responsible
关系,因此您最终会得到一个名为Responsible_Id
的表格列。