Entity Framework核心:如何添加复合object?
Entity Framework Core: How to add a composite object?
有如下复合object,例如:
public class Parent
{
[Key]
public int Id { get; set; }
[ForeignKey("ChildRefId")]
public Guid ChildId { get; set; }
public Child Child { get; set; }
}
public class Child
{
[Key]
public Guid Id { get; set; }
[ForeignKey("ParentRefId")]
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
Parent
和 Child
有 one-to-one 关系:
modelBuilder.Entity<Parent>()
.HasOne(parent => parent.Child)
.WithOne(child => child.Parent)
.WillCascadeOnDelete();
我尝试用 Child
创建新的 Parent
并将其保存在数据库中:
var parent = new Parent { Child = new Child() };
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- Exception!
...并得到以下异常:
System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Parent_Child_ChildId". The conflict occurred in database "MyDatabase", table "dbo.Child", column 'Id'.
如果我使用数据库上下文创建 child 它工作正常:
var child = dbContext.Childs.Add(new Child());
var parent = new Parent { Child = child };
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- It works fine
问题 #1: 我可以轻松地将新实体添加到嵌套集合中,而无需使用上下文来创建它。但它不适用于 one-to-one 关系。例如:
var parent = new Parent();
parent.Grandparents.Add(new Grandparent();
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- It works fine and parent with one new grandparent were created!
为什么?
问题 #2:请描述我做错了什么,以及如何在没有上下文的情况下用 child 保存新的 parent 以创建child(如嵌套集合)?
谢谢!
您应该删除流畅的语法声明(modelBuilder.Entity ...),在这种情况下不需要它。
您还需要使用您的上下文来创建对象,并且您应该指定 Id 键值。将 Int 用于键是很常见的——再加上自动数据库插入注释,为您生成键。例如
public class Child {
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("ParentRefId")]
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
您还应该使用上下文创建模型对象,例如:
using(MyDbContext db = new MyDbContext()) {
Child child = db.Childs.Create();
Parent parent = db.Parents.Create();
child.Parent = parent;
}
db.SaveChanges();
}
此错误仅发生在 beta-8
版本的 EF 中。在我将 EF 更新到 rc1-final
版本后,错误消失了。可能是因为 beta-8
版本还没有图形跟踪。
您可以找到更详细的信息here。
有如下复合object,例如:
public class Parent
{
[Key]
public int Id { get; set; }
[ForeignKey("ChildRefId")]
public Guid ChildId { get; set; }
public Child Child { get; set; }
}
public class Child
{
[Key]
public Guid Id { get; set; }
[ForeignKey("ParentRefId")]
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
Parent
和 Child
有 one-to-one 关系:
modelBuilder.Entity<Parent>()
.HasOne(parent => parent.Child)
.WithOne(child => child.Parent)
.WillCascadeOnDelete();
我尝试用 Child
创建新的 Parent
并将其保存在数据库中:
var parent = new Parent { Child = new Child() };
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- Exception!
...并得到以下异常:
System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Parent_Child_ChildId". The conflict occurred in database "MyDatabase", table "dbo.Child", column 'Id'.
如果我使用数据库上下文创建 child 它工作正常:
var child = dbContext.Childs.Add(new Child());
var parent = new Parent { Child = child };
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- It works fine
问题 #1: 我可以轻松地将新实体添加到嵌套集合中,而无需使用上下文来创建它。但它不适用于 one-to-one 关系。例如:
var parent = new Parent();
parent.Grandparents.Add(new Grandparent();
dbContext.Parents.Add(parent);
dbContext.SaveChanges(); //<-- It works fine and parent with one new grandparent were created!
为什么?
问题 #2:请描述我做错了什么,以及如何在没有上下文的情况下用 child 保存新的 parent 以创建child(如嵌套集合)?
谢谢!
您应该删除流畅的语法声明(modelBuilder.Entity ...),在这种情况下不需要它。
您还需要使用您的上下文来创建对象,并且您应该指定 Id 键值。将 Int 用于键是很常见的——再加上自动数据库插入注释,为您生成键。例如
public class Child {
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("ParentRefId")]
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
您还应该使用上下文创建模型对象,例如:
using(MyDbContext db = new MyDbContext()) {
Child child = db.Childs.Create();
Parent parent = db.Parents.Create();
child.Parent = parent;
}
db.SaveChanges();
}
此错误仅发生在 beta-8
版本的 EF 中。在我将 EF 更新到 rc1-final
版本后,错误消失了。可能是因为 beta-8
版本还没有图形跟踪。
您可以找到更详细的信息here。