EF Core可为空类型主键导致无法删除未添加实体问题咨询
针对你遇到的这个问题,我可以明确地说:这不是Bug,而是EF Core 2.2.x版本的设计限制,接下来详细解释原因和解决方案:
问题根源
EF Core跟踪实体状态时,依赖主键值来识别实体。对于非可空的int主键,当你调用Add方法时,EF Core会自动分配一个临时负数值(比如-1、-2这类)作为主键的临时值,这样后续的Remove操作可以通过这个临时值找到要删除的实体。
但对于可为空的int?主键,EF Core无法区分「主键尚未设置(null)」和「临时主键值」——因为null本身就是合法的未初始化状态,所以它不会自动生成临时负数值。当你调用Remove时,EF Core找不到可识别的主键值,就会抛出ArgumentNullException,提示key参数为空。
解决方案与建议
根据你的需求,有几种处理方式:
方案1:手动设置临时主键值
在调用Add之前,手动给Id赋值一个临时负数值(比如p1.Id = -1),这样EF Core就能跟踪到实体,后续的Remove操作可以正常执行。但这会失去你想要的「不显示延迟生成的临时Id」的优势,有点违背使用可为空主键的初衷。方案2:改用非可空主键(推荐)
这是EF Core设计时的常规用法,使用int而非int?作为主键类型,EF Core会自动处理临时主键的生成和跟踪,Add后立即Remove的场景也能正常工作。虽然会显示临时负数值,但这是EF Core内部跟踪机制的正常表现,不会影响最终数据库的主键生成(数据库依然会自动分配自增正数值)。方案3:升级EF Core版本
如果你有条件升级到EF Core 3.x及以上版本,可以测试是否有相关改进(新版本对主键跟踪的逻辑做了优化),不过2.2.4作为旧版本确实存在这个限制。
总结
EF Core 2.2.x并不推荐使用可为空类型作为自增主键,因为会破坏其内部的实体跟踪逻辑。如果你的核心需求是「不显示临时Id」,可以考虑在业务代码中对主键值做封装(比如对外暴露时隐藏临时值),而非使用可为空主键类型。
内容的提问来源于stack exchange,提问作者AgostinoX

