在引用实体的更新时不保存到不同现有实体的外键

时间:2011-11-11 19:54:24

标签: c# entity-framework ef-code-first foreign-key-relationship

我有一个引用A实体的POCO B实体,让我们说b。我希望A引用不同的现有B实体,让我们说bb

这些步骤:

var b = // get existing b from somewhere out-of-context
var a = new A { B = b }
dbcontext.Set<B>.Attach(a.B);
dbcontext.Set<A>.Add(a);
context.SaveChanges();

按预期生成a的插入语句,并将B_ID外键正确设置为主键ID b。这些后续步骤:

var bb = // get existing bb from somewhere out-of-context
a.B = bb;
differentdbcontext.Set<B>.Attach(a.B);
differentdbcontext.Set<A>.Attach(a);
differentdbcontext.Entry(a).State = EntityState.Modified;
differentdbcontext.SaveChanges();

导致持久数据无变化。更新语句未按预期包含 set B_ID = ...

我正在做一些简单的错误,因为我之前还有其他类似的工作方式。

1 个答案:

答案 0 :(得分:1)

将状态设置为Modified仅对标量属性有影响,但对导航属性没有影响。我假设B_ID不是模型中的属性,只是数据库中的外键列没有暴露给您的模型。

在这种情况下,您只能通过利用Entity Framework的自动更改检测来更新关系。一种方法 - 我称之为标准方法 - 是从数据库加载原始A 包括原始B,将a.B设置为新的bb然后保存更改:

var bb = // get existing bb from somewhere out-of-context

differentdbcontext.Set<B>().Attach(bb);
differentdbcontext.Set<A>().Include(x => x.B).Single(x => x.Id == a.Id);

a.B = bb;

differentdbcontext.SaveChanges();

如果您不想从DB加载原始文件,则需要进行一些技巧编程:

var bb = // get existing bb from somewhere out-of-context

if (  (a.B == null && bb != null) 
   || (a.B != null && bb == null)
   || (a.B != null && bb != null && a.B.Id != bb.Id)) //take care not to attach
                                                      //two objects with same key
{
    if (bb != null)
        differentdbcontext.Set<B>().Attach(bb);
    differentdbcontext.Set<A>().Attach(a);
    a.B = bb; // EF will detect this change
}
else if (a.B == null && bb == null)
{
    // create a dummy a.B
    a.B = new B(); // it doesn't matter which Id
    differentdbcontext.Set<A>().Attach(a);
    a.B = bb; // = null -> EF will detect a change
}

differentdbcontext.SaveChanges();

或类似的。我们的想法是在附加对象后更改引用,以便更改检测将FK列的更新发送到数据库。

将外键作为属性公开到模型中会使这种情况变得更加容易。将状态设置为Modified将起作用,因为FK属性是标量。