保存父实体时,不会保存新的子实体

时间:2014-08-01 11:00:07

标签: c# entity-framework entity-framework-6.1

我有一个父实体

存在于db中的

foo,我在此实体上有一个属性bar(一对多关系)。

Foo已分离,因为它使用WebApi进行反序列化,所以我这样做foo

context.Foos.AddOrUpdate(foo);

即使附加了一个新的bar引用,它也不会被保存,但是对于我们拥有的多对多关系的另一个关系它确实如此。如果我向该集合添加一个新实体,它将被保存到它的表中,并且还会在关系表中添加一行。

如果我在调用context.Bars.AddOrUpdate(foo.Bar);之前context.Foos.AddOrUpdate(foo);,它会将新栏正确保存到条形表,但它不会将正确的barId添加到foo表

@Yuliam Chandra

如果我理解你的答案是正确的(我认为你在答案中混淆了酒吧和泡沫)这应该有用吗?

var foo = new Foo();
foo.FooId = 524 //Existing foo;

foo.Bar = new Bar(); //Completely new bar    
db.Foos.AddOrUpdate(foo);
db.SaveChanges();

但它没有

1 个答案:

答案 0 :(得分:2)

使用断开连接的对象需要额外的代码。

  

如果您使用断开连接的对象,则必须手动管理   同步。

Source

如果Bar是现有实体,则需要先将其附加,因此Foo将添加为Bar's个孩子。

if (foo.Bar.Id != 0)
{
    context.Bars.Attach(foo.Bar);
    context.Foos.AddOrUpdate(foo);
}

上述代码的示例与this article中的CourseFoo)和DepartmentBar)示例类似。

但如果Bar是新实体,您只需添加Foo,那么{I}也会被添加。

Bar

可以在my answer上查看其他一些品种。

更新

在进一步解释之前,我想展示相同的代码。

  • else { context.Foos.Add(foo); } 等于db.Set<T>().Add(instance)
  • db.Entry(instance).State = EntityState.Added;等于db.Set<T>().Attach(instance)

之前的回答解释了两个条件。

  • New Foo和现有的Bar

    db.Entry(instance).State = EntityState.Unchanged;

    context.Bars.Attach(foo.Bar);

  • New Foo和New Bar

    context.Foos.AddOrUpdate(foo);

特别添加

一旦实体被标记为context.Foos.Add(foo);

Added就会有特殊情况。即使任何引用实体是数据库中的现有对象,图中的所有实体也将被标记为Added。如果我们有这个代码,将添加Foo和Bar。

Added

为了防止这种情况发生,需要首先附加Bar。

var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();

检查Julie Lerman article以获得更完整的解释。

  

它发生的原因是当你使用DbSet.Add方法时(那个   是,Screencasts.Add),不仅标记了根实体的状态   “已添加”,但图中的所有内容都没有   以前意识到标记已添加。即使是开发人员   可能知道主题具有现有的Id值,实体框架   尊重其EntityState(已添加)并创建一个Insert数据库命令   对于主题,无论现有的Id。

根据您的更新调整说明

您最新的问题是关于现有的Foo和新酒吧。使用您的代码,结果将不会添加新的Bar,现有的Foo也不会与新的Bar建立关系。

var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Bar>().Attach(bar);
db.Set<Foo>().Add(foo);
db.SaveChanges();

如果我们手动将条形码与var foo = new Foo(); foo.FooId = 524 //Existing foo; foo.Bar = new Bar(); //Completely new bar db.Foos.AddOrUpdate(foo); db.SaveChanges(); 一起添加,结果仍然不符合预期。新栏将被添加,但Foo将与新栏没有关系。

AddOrUpdate(foo)

db.Bars.Add(foo.Bar); db.Foos.AddOrUpdate(foo); 的行为不一致。

解决方案

  

如果您使用断开连接的对象,则必须手动管理   同步。

此代码应适用于所有条件。

  • New Foo和New Bar
  • New Foo和现有酒吧
  • 现有的Foo和New Bar
  • 现有Foo和现有栏

此代码取决于id(id = 0是一个新实体)。

AddOrUpdate

db.Entry(foo).State = foo.FooId == 0 ? EntityState.Added : EntityState.Modified; if (foo.Bar != null) { db.Entry(foo.Bar).State = foo.Bar.BarId == 0 ? EntityState.Added : EntityState.Modified; ^^^ // If you don't want to change the Bar while creating a relationship between // Foo and with existing Bar, you can change // `EntityState.Modified` with `EntityState.Unchanged` } db.SaveChanges(); 相关,我认为可以找到一个未解决的问题here