【问题标题】:How to add an entity in EF5 that has child entities but without updating those children如何在 EF5 中添加具有子实体但不更新这些子实体的实体
【发布时间】:2014-01-02 17:05:18
【问题描述】:

我在 Visual Studio 2012 中使用 EF5 和 POCO 类以及 .Net Framework 4.5。我的父子关系如下:

public class Parent {
  [Key]
  public int Id {set; get}
  public string Name {set; get;}
  public int ChildId {set; get;}
  public virtual Child Child { get; set; }
}

public class Child {
      [Key]
      public int Id {set; get}
      public string Name {set; get;}
}

我在 Web Api 场景中使用 EF5。客户端希望通过发送 JSON 来创建一个新的 Parent:

{ 
Id: 0, 
Name:'Spock', 
ChildId: 42
}

javascript 客户端不必提供子对象,只需提供键即可。

但是,要做到这一点,这意味着在 Web Api 方法中,我必须读取 Child 实体并将其设置为 Parent.Child,如下所示:

    parent.Child= (from child in db.Child where child.Id == parent.ChildId select child).FirstOrDefault();
    db.Parent.Attach(parent);
db.Entry(parent).State = System.Data.EntityState.Added;

如果我没有将 parent.Child 设置为 key 对应的实例,那么 EF 会抛出异常:

ExceptionMessage=A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.

我也尝试过像这样添加新的父对象:

db.Parent.Add(parent);

其中 parent.Child 为 null,但随后 Entity Framework 生气并说:

ExceptionMessage=Cannot insert the value NULL into column 'Name', table 'MyDB.dbo.Child'; column does not allow nulls. INSERT fails.
The statement has been terminated.

有没有一种方法可以插入一个新的 Parent 行,而无需读取所有子实例,只需设置它们的键?我希望 Parent POCO 类在 GET(读取)数据时填充子级,所以我想要那里的虚拟子属性,但我不希望客户端能够更新子级。我可以以某种方式告诉 EF 在添加或附加期间忽略孩子吗?在我的示例中,有一个孩子处于 1:1 的关系中,但可以有很多和 1:many 的关系,所以这可能会变得非常丑陋,并且会对性能造成很大的影响。

总之,我根本不希望 EF 创建子行或更新子行,如何阻止它以不涉及从数据库中读取和设置所有子实体的方式更新子实体?

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    此关系中的“主要”实体是子实体(子记录必须存在于数据库中,然后才能添加父记录”。“依赖”实体是父实体,只有当子实体在数据库中可用时才能添加. 你的名字和这个不太相符......

    子实体可能应该有一个父导航属性

    public ICollection<Parent> Parents { get; set; }
    

    并且您将需要一个映射以将该导航返回到父记录

    HasMany(c => c.Parents).WithRequired().HasForeignKey(p => p.ChildId);
    

    那么只要子记录已经存在于数据库中就可以直接写

    db.Parents.Add(newParent);
    

    【讨论】:

    • A.在这个例子中说“产品”而不是“父母”和“类别”而不是“孩子”是更正确的,你在理解预期的依赖/原则关系方面是正确的。
    • B. 如果我将 navigator 添加回 Parent,那么我将需要处理 Json 自引用循环问题,然后关闭 ProxyCreation,然后找出 Eager loading 或 Query Paths。 C. 我还没有找到一个很好的例子,大量的文章试图解决这个问题。有没有人知道的综合例子? D. EF6 是否更擅长处理这种情况?
    • 或者你使用 ViewModel。通常,您创建一个仅在视图和控制器之间来回传递所需属性的 ViewModel。这些可能与您的实体相同,没有导航属性,但通常它们往往不同,具有投影数据和/或计算字段。在复杂实体中,它们通常只是您正在使用的视图所需的属性。
    猜你喜欢
    • 2014-11-30
    • 2015-01-26
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    相关资源
    最近更新 更多