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

发布于 2024-12-15 05:04:57 字数 824 浏览 0 评论 0原文

我有一个 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 = ...

我正在做一些简单的错误,因为我以前也遇到过类似的情况。

I have a POCO A entity referencing a B entity, let's say b. I want A to reference a different exising B entity, let's say bb.

These steps:

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

generate an insert statement for a as expected with the B_ID foreign key properly set to the primary key ID of b. These subsequent steps:

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

result in no change to the persisted data. The update statement does not include the set B_ID = ... as expected.

I'm doing something simple wrong as I've had other scenarios like this working before.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断爱 2024-12-22 05:04:57

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

在这种情况下,您只能通过利用实体框架的自动更改检测来更新关系。一种方法 - 我将其称为标准方法 - 是从数据库加载原始 A 包括原始 B,设置 aB 到您的新 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();

如果您不想从数据库加载原始数据,则需要一些技巧编程:

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 属性是标量。

Setting the state to Modified only has an effect on scalar properties but not on your navigation properties. I assume that B_ID is not a property in your model but only the foreign key column in the database not being exposed to your model.

In this case you can update the relationship only by leveraging the automatic change detection of Entity Framework. One approach - and I would call this the standard approach - is to load the original A including the original B from the database, set a.B to your new bb and then save the changes:

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

If you don't want to load the original from the DB some trick programming is required:

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

Or similar. The idea is to change the reference after attaching the objects so that change detection will send an update of the FK column to the database.

Exposing foreign keys as properties into your model will make this situation much easier. Setting the state to Modified would work then because FK properties are scalar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文