我有一个父实体

foo 存在于数据库中,我有一个属性 bar 在此实体上(一对多关系)。

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

context.Foos.AddOrUpdate(foo);

就算有新的 bar 附加到它的引用,它不会被保存,但是对于我们拥有的另一个关系(多对多关系)来说,它确实像这样工作。如果我向该集合添加一个新实体,它将被保存到其表中,并且还会向关系表中添加一行。

如果我做 context.Bars.AddOrUpdate(foo.Bar); 打电话之前 context.Foos.AddOrUpdate(foo); 它会将新的 bar 正确保存到 bar 表中,但不会将正确的 barId 添加到 foo 表中

@尤利亚姆·钱德拉

如果我正确理解你的答案(我认为你在答案中混淆了 bar 和 foos),这应该可行吗?

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

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

但事实并非如此

有帮助吗?

解决方案

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

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

来源

如果 Bar 是一个现有实体,您需要先附加它,所以 Foo 将被添加为 Bar's 孩子们。

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

上面代码的例子类似 Course (Foo) 和 Department (Bar) 中的示例 本文.

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

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

其他一些品种可以检查 我的答案.

更新

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

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

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

  • 新 Foo 和现有 Bar

    context.Bars.Attach(foo.Bar);

    context.Foos.AddOrUpdate(foo);

  • 新Foo和新酒吧

    context.Foos.Add(foo);

特别添加

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

查看 朱莉·勒曼文章 以获得更完整的解释。

发生的原因是,当您使用dbset.add方法(即ScreenCasts.Add)时,不仅是“添加”根实体的状态也添加了标记。即使开发人员可能意识到该主题具有现有的ID值,Entity Framework仍会尊重其实体state(添加)并为主题创建插入数据库命令,而不论现有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 和新的 Bar
  • 现有的 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, ,我认为有一个未解决的问题可以找到 这里.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top