实体框架试图插入父对象

Mar*_*lef 2 c# entity-framework

问题

我正在使用Entity Framework将复杂的对象模型添加到数据库中.我遇到一个问题,我试图插入一个子对象,EF也试图插入父对象,这导致数据库中的完整性问题.

说明

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

  1. ShopPerformance

商店可以有许多ShopPerformance条目,ShopPerformance必须有商店,商店记录已经存在于数据库中(因此EF应该不管它并专注于ShopPerformance).

在我的示例中,我只尝试添加ShopPerformance(在这种情况下,ShopPerformance的实例称为"性能":

this.db.Entry(performance).State = System.Data.EntityState.Added;
this.db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

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

我试过的事情

我已经尝试将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;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,EF以某种方式重新建立商店和性能之间的链接,并尝试再次插入商店.

然后我尝试了:

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;
Run Code Online (Sandbox Code Playgroud)

这会导致空引用异常.

期望的决议

我正在寻找一种方法来插入我的表演对象而不用EF摆弄商店.这完全打破了我的工作.

TL; DR

我希望实体框架只插入/更新我告诉它的对象,而不是任何相关对象.我怎样才能做到这一点?

Yul*_*dra 5

你与断开连接的对象的工作,无论是performanceperformance.Shop是不是由EF跟踪实体和EF不知道是什么的状态performance.Shop.

performance使用现有添加new 时performance.Shop,EF不知道它performance.Shop是现有实体,EF也会在图中标记所有未跟踪的对象Added.

它发生的原因是,当您使用DbSet.Add方法(即Screencasts.Add)时,不仅将根实体的状态标记为"已添加",而且图中的所有内容都是上下文之前未了解的标记已添加.- MSDN

你需要做的是.

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

    performance.ShopId = performance.Shop.Id;
    performance.Shop = null;
    this.db.Entry(performance).State = System.Data.EntityState.Added;
    this.db.SaveChanges();
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者您需要performance.Shop通过首先将(status = Unchanged)附加到上下文来让EF知道它是现有实体.

    this.db.Entry(performance.Shop).State = EntityState.Unchanged;
    this.db.Entry(performance).State = EntityState.Added;
    this.db.SaveChanges();
    
    Run Code Online (Sandbox Code Playgroud)