.NET 6迁移时Dynamic LINQ报“Nullable object must have a value”错误求助
.NET 6迁移后Dynamic LINQ左连接查询抛出Nullable对象必须有值异常
原.NET Core 3.1可运行代码
query = query.GroupJoin(ParsingConfig.DefaultEFCore21, detailObject, "new { it.ExternalDataId2.Value AS I0}", "new { Id AS I0}", "new (outer AS A, inner AS B)"); query = query.SelectMany("B.DefaultIfEmpty()", "new { source.A.Id AS Id,source.A.ExternalDataId2 AS ExternalDataId2,detail.Title AS ExternalData2Ref_Title,detail.Id AS ExternalData2Ref_Id}", "source", "detail"); query.ToDynamicListAsync();
迁移至.NET 6后的错误
异常提示:
Nullable object must have a value.
完整异常堆栈:
Message: Test method FrameworkTests.DataLayer.FindTests.FindValueExternal threw exception: NTSFramework.DataLayer.DataLayerException: Errore generico di repository Nullable object must have a value. ---> System.InvalidOperationException: Nullable object must have a value. Stack Trace: lambda_method559(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator ) AsyncEnumerator.MoveNextAsync() DynamicEnumerableAsyncExtensions.ToListAsync[T](IEnumerable source, CancellationToken cancellationToken) DynamicEnumerableAsyncExtensions.ToListAsync[T](IEnumerable source, CancellationToken cancellationToken) BaseDataLayer.FindValuesAsync[TModel](FindValuesOptions findOptions) line 866
注:通过SQL Profiler可见查询已执行,移除ParsingConfig无法解决问题。
尝试过的修改(可运行但无法得到所需结果)
query = query.SelectMany("B.DefaultIfEmpty()", "new { source.A.Id AS Id,source.A.ExternalDataId2 AS ExternalDataId2,detail As ExternalData2Ref}", "source", "detail");
解决方案
问题原因
.NET 6对Nullable类型的检查和EF Core的结果映射逻辑更严格。由于使用DefaultIfEmpty()实现左连接,当detail(即B表无匹配数据)为null时,直接访问detail.Title或detail.Id会触发异常——如果这些属性是非Nullable值类型(如int),EF Core 6不允许将null映射到非Nullable字段,而.NET Core 3.1可能默认忽略了这个检查。
修改后的代码
在SelectMany的投影表达式中,为detail的属性添加空值判断:
query = query.SelectMany("B.DefaultIfEmpty()", "new { source.A.Id AS Id,source.A.ExternalDataId2 AS ExternalDataId2,detail == null ? null : detail.Title AS ExternalData2Ref_Title,detail == null ? null : detail.Id AS ExternalData2Ref_Id}", "source", "detail");
说明
- 通过
detail == null ? null : detail.XXX的三元判断,确保当detail为null时返回null,而非强制访问非Nullable属性。 - 如果
detail.Id是值类型(如int),需要确保目标模型中对应的ExternalData2Ref_Id字段是可空类型(如int?),否则仍会出现映射错误。
内容的提问来源于stack exchange,提问作者Paolo Crociati
相关产品推荐
相关产品推荐

