实体框架核心 - 无法删除可选的可为空关系
Posted
技术标签:
【中文标题】实体框架核心 - 无法删除可选的可为空关系【英文标题】:Entity Framework Core - Cannot remove optional nullable relationship 【发布时间】:2021-09-18 07:42:36 【问题描述】:使用Microsoft.EntityFrameworkCore
版本5.0.7
和Npgsql.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 我已经删除了我所有的帖子,因为他们侮辱了你。我不是这个意思,没有私人的。我刚刚发表了我的看法。以上是关于实体框架核心 - 无法删除可选的可为空关系的主要内容,如果未能解决你的问题,请参考以下文章