【发布时间】:2020-02-13 11:28:02
【问题描述】:
我有标准的父/子设计:
class Parent {
Guid Id;
List<Child> Children;
public Parent() {
Id = Guid.NewGuid();
this.Children = new List<Child>();
}
public AddChild(Child ch) {
this.Children.Add(ch);
}
}
class Child {
Guid Id;
public Child() {
Id = Guid.NewGuid();
}
}
我的映射是这样的:
public void Configure(EntityTypeBuilder<Parent> builder)
{
builder.ToTable("Parents");
builder.HasKey(x => x.Id);
builder.HasMany(p => p.Children)
.WithOne()
.HasForeignKey("ParentId");
}
public void Configure(EntityTypeBuilder<Child> builder)
{
builder.ToTable("Children");
builder.HasKey(x => x.Id);
}
现在,在我的服务方法中(将子添加到父级,在系统中不存在的情况下创建父级):
var parent = await _parentsRepository.GetParent(parentId);
if (parent == null)
{
parent = new Parent();
await _parentsRepository.AddAsync(customerMembersip); // adding parent to context, with empty Children collection, but not saving to DB yet
}
parent.AddChild(new Child()); // this make this new Child in Parent object to be in state "Modified", but in fact should be in state "Added". Why?
// save changes here
换句话说,为什么将子级添加到父级(父级只是添加到上下文中)会使子级被视为已修改?但是,如果我从 repo 中获取父级并且它立即在上下文中,然后我添加子级,那么子级将被视为 已添加。
编辑:
这可能是因为 Id(Guid 类型)是在 C# 代码中生成的,因此 EF“认为”它是现有实体,因此将其标记为“已修改”。但我不太明白为什么,如果 Parent 已经存在于 DB 中(_parentsRepository 返回实际实体)
【问题讨论】:
-
(1) 请重命名您的“Id”以区分它们。 ParentId(或ParentKey)和ChildId(或ChildKey。(2)我认为您需要添加互惠关系。(在Child.configure上)示例: this.HasRequired(t => t.Parent) .WithMany(t => t .Children) .HasForeignKey(d => d.ParentKey);
-
继续。您的 Child 对象需要像“Parent MyParent {get;set}”这样的属性。然后在您的方法“public AddChild(Child ch)”上,您需要添加一个新行 .. 类似“ch.MyParent = this;”
-
我会尝试这种方法,但它违反了 DDD,因为在我的业务案例中,我根本不需要双向关系。仅仅因为 EF 不喜欢“预生成的 Guid”而增加一点复杂性并不适合我。
-
EF 是关于“互惠”关系的,至少在我的经验中是这样。如果您想(仅)添加一个子项,那么数据库如何知道父项的 FK 是什么? (没有 Child 上的“Parent MyParent {get;set}”属性?)
-
互惠是在映射(配置文件)级别定义的。根据我的经验,在您的域模型中不需要有双向关系。
标签: entity-framework ef-core-2.2