实体框架试图插入父对象

时间:2014-08-22 04:36:29

标签: c# entity-framework

问题

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

解释

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

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

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

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

    当我调用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;
    

    在这种情况下,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;
    

    这会导致空引用异常。

    所需的解决方案

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

    TL; DR

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

2 个答案:

答案 0 :(得分:5)

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

在使用现有performance添加新的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();
    
  • 或者您需要让EF知道performance.Shop是现有实体,首先将(status = Unchanged)附加到上下文中。

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

答案 1 :(得分:1)

你有没有尝试过:

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();