实体框架试图插入父对象

本文关键字:对象 插入 框架 实体 | 更新日期: 2023-09-27 18:19:06

问题

我使用实体框架添加一个复杂的对象模型到数据库。我遇到了一个问题,我试图插入一个子对象,EF也试图插入父对象,这会导致数据库中的完整性问题。

对于我的例子,让我们假设我们有两个表:

    <
  1. 商店/gh>
  2. ShopPerformance

一个Shop可以有许多ShopPerformance条目,ShopPerformance必须有一个Shop,并且Shop记录已经存在于数据库中(因此EF应该将其单独放置并专注于ShopPerformance)。

在我的例子中,我试图只添加ShopPerformance(在这种情况下,ShopPerformance的实例被称为"performance":

this.db.Entry(performance).State = System.Data.EntityState.Added;
this.db.SaveChanges();

当我调用SaveChanges()时,EF也试图插入商店,这会导致数据库中的约束错误,因为它有约束来防止重复条目(基于商店的名称)。

Things I've try

我已经尝试将ShopPerformance中的Shop属性设置为null,以阻止EF做我不想做的事情(它仍然具有ShopID作为单独的属性)。首先我试着:

Shop theShop = performance.Shop;
performance.Shop = null;
this.db.Entry(performance).State = System.Data.EntityState.Added;
this.db.SaveChanges();
performance.Shop = theShop;

在这种情况下,EF以某种方式重新建立了shop与绩效之间的联系,并试图再次插入shop。

Then I try:

Shop theShop = performance.Shop;
this.db.Entry(performance).Entity.Shop = null;
this.db.Entry(performance).State = System.Data.EntityState.Added;
this.db.SaveChanges();
this.db.Entry(performance).Entity.Shop = theShop;

这将导致空引用异常。

所需的分辨率

我正在寻找一种方法来插入我的性能对象没有EF摆弄周围的商店。这完全打乱了我的工作。

TL;博士

我希望实体框架只插入/更新我告诉它的对象,而不是相关对象。我该怎么做呢?

实体框架试图插入父对象

您正在处理断开连接的对象,performanceperformance.Shop都是EF不跟踪的实体,EF不知道performance.Shop的状态是什么。

当用现有的performance.Shop添加新的performance时,EF不知道performance.Shop是一个存在的实体,EF也会将图中所有未跟踪的对象标记为Added

发生这种情况的原因是当您使用DbSet时。添加方法是,Screencasts.Add),不仅根实体的状态被标记"添加",但图表中上下文没有的所有内容也被标记为"添加"。——MSDN

你需要做的是。

  • 如果你有外键关联,你可以只分配id而不是引用。

    performance.ShopId = performance.Shop.Id;
    performance.Shop = null;
    this.db.Entry(performance).State = System.Data.EntityState.Added;
    this.db.SaveChanges();
    
  • 或者你需要让EF知道performance.Shop是一个存在的实体,首先将(status = Unchanged)附加到上下文。

    this.db.Entry(performance.Shop).State = EntityState.Unchanged;
    this.db.Entry(performance).State = EntityState.Added;
    this.db.SaveChanges();
    

你试过了吗:

var shop = this.db.shops.Find(id);
shop.Performances.Add(new Performance());
this.db.SaveChanges();

this.db.performances.Add(new Performance() { ShopId = id });
this.db.SaveChanges();