处理断开的对象需要额外的代码。
如果您正在处理断开连接的对象,则必须手动管理
同步。
Source
如果Bar 是现有实体,您需要先附加它,所以Foo 将被添加为Bar's 子实体。
if (foo.Bar.Id != 0)
{
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
}
上述代码示例与this article中的Course (Foo) 和Department (Bar) 示例类似。
但如果Bar是一个新实体,你只需添加Foo,那么Bar也会被添加。
else
{
context.Foos.Add(foo);
}
其他品种可以在my answer上查看。
更新
在进一步解释之前,我想显示相同的代码。
-
db.Set<T>().Add(instance) 等于 db.Entry(instance).State = EntityState.Added;
-
db.Set<T>().Attach(instance) 等于 db.Entry(instance).State = EntityState.Unchanged;
上一个答案解释了两个条件。
特别添加
Added 具有特殊条件,一旦实体被标记为Added。图中的所有实体也将被标记为Added,即使任何引用实体是数据库中的现有对象。如果我们有这个代码,就会添加 Foo 和 Bar。
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();
为了防止这种情况发生,需要先附加 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();
查看Julie Lerman article 以获得更完整的说明。
发生这种情况的原因是当您使用 DbSet.Add 方法时(即
即,Screencasts.Add),不仅标记了根实体的状态
“已添加”,但图中没有上下文的所有内容
之前知道的也标记为已添加。尽管开发商
可能知道该主题有一个现有的 Id 值,实体框架
尊重其 EntityState(已添加)并创建插入数据库命令
对于主题,不管现有的 Id。
根据您的更新调整说明
您更新的问题是关于现有的 Foo 和新的 Bar。使用您的代码,结果不会添加新的 Bar 并且现有的 Foo 不会与新的 Bar 建立关系。
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
如果我们手动将Bar与AddOrUpdate(foo)一起添加,结果仍然不如预期。新的 Bar 会被添加,但 Foo 不会与新的 Bar 有关系。
db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);
AddOrUpdate 的行为不一致。
解决方案
如果您正在处理断开连接的对象,则必须手动管理
同步。
此代码应适用于所有条件。
- 新 Foo 和新酒吧
- 新的 Foo 和现有的酒吧
- 现有 Foo 和新酒吧
- 现有的 Foo 和现有的 Bar
这段代码取决于id(id = 0 是一个新实体)。
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相关,我认为有一个未解决的问题可以在here找到。