在更新引用实体时不保存不同现有实体的外键
本文关键字:实体 保存 更新 引用 | 更新日期: 2023-09-27 18:14:34
我有一个POCO A
实体引用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
外键正确设置为b
的主键ID。下面的步骤:
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 = ...
。
我正在做一些简单的错误,因为我以前有过类似的工作场景
将状态设置为Modified
只对标量属性有影响,但对导航属性没有影响。我假设B_ID
不是你的模型中的属性,而只是数据库中的外键列,不暴露给你的模型。
在这种情况下,您只能通过利用实体框架的自动变更检测来更新关系。一种方法——我称之为标准方法——是从数据库中加载原始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属性是标量。