.NET Core 3.1迁移至.NET 6后出现Nullable object取值错误求助
问题分析与解决方案
一、为啥.NET Core 3.1里没问题?
.NET Core 3.1配套的EF Core 3.x对空值处理比较宽松:左连接返回的实体如果为null,EF会自动给非可空值类型属性(比如int、DateTime)填充默认值(比如0、1900-01-01),不会直接抛出空值异常。而.NET 6搭配的EF Core 6.0严格遵循可空引用类型规则,再加上.NET 6默认启用了可空引用类型检查,当你访问一个标记为非可空但实体实际为null的属性时,就会直接抛出「Nullable object must have a value」错误,不再自动填充默认值。
二、批量处理的几种实用方案
1. 用GetValueOrDefault()兜底值类型属性
针对int、DateTime这类值类型,调用该方法可在实体为null时返回类型默认值,避免异常:
// 原错误写法 Id = t2.Id, // 修改后 Id = t2?.Id.GetValueOrDefault() ?? 0,
2. 左连接时指定默认实体
在DefaultIfEmpty()中创建一个带默认值的实体,后续访问属性无需担心null:
from t1 in db.Table1 join t2 in db.Table2 on t1.Id equals t2.T1Id into t2Group // 给左连接结果设置默认实体,属性赋值合理默认值 from t2 in t2Group.DefaultIfEmpty(new Table2 { Id = 0, Name = "" }) // 直接访问t2.Id、t2.Name即可
3. 临时开启兼容模式(不建议长期使用)
如果想快速恢复旧行为,可在DbContext中配置让EF回到旧版空值处理逻辑:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的连接字符串", opt => opt.UseRelationalNulls()); }
这只是权宜之计,长期依赖会掩盖潜在空值问题,不符合.NET 6的设计理念。
4. 给实体类属性添加可空标记
从根源解决问题,将左连接对应的实体属性改为可空类型,值类型属性也标记为可空:
// 原实体属性 public Table2 T2 { get; set; } public int T2Id { get; set; } // 修改后 public Table2? T2 { get; set; } public int? T2Id { get; set; }
这样代码符合.NET 6的可空规范,后续不会再出现同类问题。
5. 用三元判断替代空传播运算符
由于EF表达式树不支持?.,换成三元判断即可解决编译报错:
// 原错误写法(编译报错) Name = t2?.Name, // 修改后 Name = t2 != null ? t2.Name : null,
内容的提问来源于stack exchange,提问作者Tufan Chand
相关产品推荐
相关产品推荐

