.NET Core 3.1迁移至.NET 7时出现“Nullable object must have a value”异常求助
.NET Core 3.1迁移.NET7 EF Core "Nullable object must have a value" 异常解决方案
异常原因
EF Core从.NET 5开始调整了左连接(DefaultIfEmpty())中非可空值类型的处理逻辑:当关联表无匹配数据时,不再自动为实体的非可空值类型属性(如int、DateTime)填充默认值,而是尝试将null赋值给非可空属性,触发"Nullable object must have a value"异常。而.NET Core 3.1中EF Core会自动为这类属性填充默认值(如int填0、DateTime填DateTime.MinValue)。
解决方案
1. 全局配置恢复旧行为(推荐,适配大量遗留代码)
在DbContext的OnConfiguring方法中添加UseRelationalNulls(false)配置,强制EF Core回到.NET Core 3.1的null处理逻辑:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer("你的数据库连接字符串") // 根据实际数据库替换驱动,比如UseInMemoryDatabase .UseRelationalNulls(false); // 关键配置,恢复自动填充默认值的行为 }
说明:
UseRelationalNulls是EF Core 3.0引入的API,设置为false时,EF Core会将数据库返回的null值转换为对应CLR类型的默认值,避免赋值非可空属性时抛出异常。
2. 局部查询调整(适合少量代码场景)
若不想全局修改,可在查询中手动为可能为null的实体指定默认对象,但此方式需逐个修改查询,仅适合少量场景:
var query = from p in dbContext.Products.Where(p => dto.Ids.Contains(p.Id)) from c in dbContext.Categorys.Where(c => c.Id == p.CategoryId).DefaultIfEmpty() from wh in dbContext.Warehouses.Where(wh => wh.Id == p.WarehouseId).DefaultIfEmpty() select new { Product = p, Category = c ?? new Category { Id = 0, Name = string.Empty }, Warehouse = wh ?? new Warehouse { Id = 0, Location = string.Empty } };
补充说明
- 全局配置
UseRelationalNulls(false)会作用于整个DbContext的所有查询,完全模拟.NET Core 3.1的行为,是处理大量遗留代码的最优方案。 - 若后续计划逐步优化代码,可先通过全局配置过渡,再逐步将实体类的非可空值类型改为可空类型(如
int→int?),同时调整业务逻辑处理null场景。
内容的提问来源于stack exchange,提问作者Dan Van
相关产品推荐
相关产品推荐

