实体框架核心 - 无法删除可选的可为空关系

Posted

技术标签:

【中文标题】实体框架核心 - 无法删除可选的可为空关系【英文标题】:Entity Framework Core - Cannot remove optional nullable relationship 【发布时间】:2021-09-18 07:42:36 【问题描述】:

使用Microsoft.EntityFrameworkCore 版本5.0.7Npgsql.EntityFrameworkCore.PostgreSQL 版本5.0.7,我目前无法尝试删除关系并存储该更改。假设有两个模型:

public class Banana 
  public int Id  get; set; 
  public Consumer? Consumer  get; set; 

public class Consumer 
  public int Id  get; set; 

我可以很好地分配消费者

myBanana.Consumer = dbContext.Consumers.First(row => row.Id == 1);
dbContext.Update(myBanana);
dbContext.SaveChanges();

而且效果很好 - 数据库会相应更新。但是,一旦存储,尝试再次使用删除引用

myBanana.Consumer = null;
dbContext.Update(myBanana);
dbContext.SaveChanges();

失败。保存后,旧值仍在数据库中,而不是我期望的null。有趣的是,对香蕉的其他更改保存得很好。

我不确定我是否遇到了 Nullables 的奇怪问题,或者我只是遗漏了一些东西,所以我很感激一些提示。

【问题讨论】:

这个 public int Consumer 是什么?消费者得到;放; 你怎么能编译它? @Serge 这是一个可以为空的值类型见docs.microsoft.com/en-us/dotnet/csharp/language-reference/… @Serge 请原谅,错误地试图简化模型以使其适合。那应该是public Consumer? Consumer get; set; - 相应地进行了编辑。 :) 【参考方案1】:

如果您想继续使用auto-generated foreign key properties,您必须确保导航已加载。如果默认情况下它们是延迟加载的并且您没有手动加载它们,则在您尝试分配 null 之前,该属性已经是 null,因此 EF 无法观察到变化。

使用.Include(banana => banana.Consumer) 加载导航有效,通过dbContext.Entry(myBanana).Reference(banana => banana.Consumer).Load() 加载导航也是如此。加载相关导航项后,问题示例中的myBanana.Consumer = null 将按预期工作。


如果您有一个非跟踪实体可以使用(例如因为它是由模型绑定生成的),您可以获取一个跟踪实体,或者直接更改自动生成的外键影子属性的值:

dbContext.Entry(myBanana).Property("ConsumerId").CurrentValue = null;

这也有效。由于您依赖字符串作为正确的字段名称,因此这可能不太完善,但根据具体情况,它可能是一个有效的选项。

【讨论】:

考虑不接受当前接受的答案并接受你的。它不是:除了它,因为“修复你的课程”不是特定问题的答案,绝对不是强制性的。 作为记录,我在上游提交了一个错误报告:github.com/dotnet/efcore/issues/25217,以便维护人员可以决定这是可接受的副作用还是应该解决的问题。 @IvanStoev 只能在 2 天内接受我自己的答案,但会这样做,因为这是一个好点。谢谢! @Serge,恕我直言,您可能会注意到我在回答中解释了主要问题,但如果无法选择跟踪实体,也建议了一个可能的替代方案。绝对不是由你来决定人们应该做什么和不应该做什么——特别是如果我在这里描述的内容 100% 被官方文档覆盖。 “真正的专业人士”会接受有多种方法可以实现目标,每种方法都有自己的优点。大喊“看起来很荒谬”、“专业人士会感到羞耻”和“修复你的模型”不利于富有成效和尊重的讨论。 @DennisSchubert 我已经删除了我所有的帖子,因为他们侮辱了你。我不是这个意思,没有私人的。我刚刚发表了我的看法。

以上是关于实体框架核心 - 无法删除可选的可为空关系的主要内容,如果未能解决你的问题,请参考以下文章

XCode - 删除核心数据中的相关对象

处理 Net 6 的可为空和实体框架实体 [关闭]

与实体框架 ASP.net MVC 中多个表的可选关系

使用实体框架中的可选记录级联删除

CoreData 对多的可选关系永远不能为零?

首先在实体框架数据库中级联删除