保存父实体时,新的subentity不会保存 [英] New subentity will not save when parent entity is saved

查看:167
本文介绍了保存父实体时,新的subentity不会保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个父实体

foo 存在于db中,我有一个属性 bar 在这个实体(一对多关系)。

foo which exists in the db, I have a property bar on this entity (One to many relation).

Foo 是分离的,因为它反序列化使用WebApi,所以我这样做到 foo

Foo is detached because its deserialized using WebApi, so I do this to foo

context.Foos.AddOrUpdate(foo);

即使有新的附加它,它不会得到保存,但它确实像这样工作为另一个关系,我们有一个多对多的关系。如果我向该集合添加了一个新实体,它将被保存到其表中,并且还将一行添加到关系表中。

Even If there is a new bar reference attached to it, it wont get saved, however it does work like this for another relation we have which is a Many to many relation. If I add a new entity to that collection it will be saved to its table and also a row is added to the relation table.

如果我执行 context.Foos.AddOrUpdate(foo); 之前,将正确保存新的栏,上下文.Bars.AddOrUpdate(foo.Bar); 到酒吧桌子,但是它不会在foo表中添加正确的barId

If I do context.Bars.AddOrUpdate(foo.Bar); before calling context.Foos.AddOrUpdate(foo); it will save the new bar correctly to the bar table, but it wont add the correct barId to the foo table

@Yuliam Chandra

如果我正确地理解你的答案(我认为你在你的答案中混合了酒吧和foos)这应该是有效的。

If i understand your answer correctly (I think you are mixing up bars and foos in your answer) this should work?

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

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

但它不

推荐答案

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

Working with disconnected objects needs extra code.


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

If you are working with disconnected objects you must manually manage the synchronization.

来源

如果 Bar 是现有实体您需要先附加它,因此 Foo 将被添加为 Bar的孩子。

If Bar is an existing entity you need to attach it first, so Foo will be added as Bar's children.

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

上述代码的示例与课程 Foo )和部门 Bar )示例在这篇文章

The example of above code is similar with Course (Foo) and Department (Bar) example in this article.

但如果 Bar 是一个新实体,您只需要添加 Foo ,然后 Bar 也将被添加。

But if Bar is a new entity you just need to add Foo, then Bar will also be added.

else
{
    context.Foos.Add(foo);
}

可以在我的回答

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

Before explaining further, I'd like show identical code.


  • db.Set< T>()实例)等于 db.Entry(instance).State = EntityState.Added;

  • db.Set< T>()。附加(实例)等于 db.Entry(instance).State = EntityState.Unchanged;

  • db.Set<T>().Add(instance) equals to db.Entry(instance).State = EntityState.Added;
  • db.Set<T>().Attach(instance) equals to db.Entry(instance).State = EntityState.Unchanged;

以前的答案解释了两个条件。

The previous answer explained about two conditions.


  • New Foo和现有的栏

  • New Foo and existing Bar

context.Bars.Attach(foo.Bar);

context.Foos.AddOrUpdate(foo);

New Foo and new Bar

New Foo and new Bar

context.Foos.Add(foo); / p>

context.Foos.Add(foo);

已添加有特殊条件,一次一个实体被标记为添加。即使任何引用实体是数据库中的现有对象,图表中的所有实体都将被标记为也添加了。如果我们有这个代码,Foo和Bar将被添加。

Added has special condition, once an entity is marked as Added. all the entities in the graph will be marked as Added too, even if any reference entity is an existing object in the database. If we have this code, Foo and Bar will be added.

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

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

To prevent that from happening, Bar needs to be attached first.

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

检查 Julie Lerman文章,以获得更完整的解释。

Check Julie Lerman article for more complete explanation.


发生的原因是当你使用DbSet.Add方法(那个
是,Screencasts.Add)时,根本实体的状态不仅标记为
已添加,而且图中的所有内容都是上下文不是
以前意识到被标记为已添加。即使开发人员
可能意识到主题具有现有的Id值,实体框架
尊重其EntityState(已添加),并为主题创建一个Insert数据库命令
,而不管现有的

The reason it happens is that when you use the DbSet.Add method (that is, Screencasts.Add), not only is the state of the root entity marked "Added," but everything in the graph that the context was not previously aware of is marked Added as well. Even though the developer may be aware that the Topic has an existing Id value, Entity Framework honors its EntityState (Added) and creates an Insert database command for the Topic, regardless of the existing Id.



根据您的更新调整说明



您的更新问题关于现有的Foo和新酒吧。使用你的代码,结果将不会添加新的栏,现有的Foo将不会与新的Bar关系。

Adjust Explanation Based On Your Update

And your updated question is about existing Foo and new Bar. Using your code, the result will not add new Bar and existing Foo will not make a relationship with new Bar.

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

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

如果我们手动添加栏与 AddOrUpdate(foo),结果仍然不如预期。新的栏将被添加,但是Foo将不会与新的Bar关系。

If we manually add the Bar together with AddOrUpdate(foo), the result is still not as expected. The new Bar will be added, but Foo will not have relationship with the new Bar.

db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);

AddOrUpdate 的行为不一致。 / p>

解决方案



The behavior of AddOrUpdate is inconsistent.


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

If you are working with disconnected objects you must manually manage the synchronization.

此代码应该在所有条件下工作。

This code should work in all conditions.


  • 新Foo和新酒吧

  • 新的Foo和现有酒吧

  • 现有的Foo和新酒吧

  • 现有Foo和现有栏

  • New Foo and New Bar
  • New Foo and Existing Bar
  • Existing Foo and New Bar
  • Existing Foo and Existing Bar

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

This code depends on the id (id = 0 is a new entity).

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

AddOrUpdate 相关,我认为有一个公开的问题,可以在这里找到。

Related to AddOrUpdate, I think there is an open issue that can be found here.

这篇关于保存父实体时,新的subentity不会保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆