ASP.NET Web API中Linq查询为null字段设默认值报错解决
解决ASP.NET Web API中Linq查询空关卡记录的默认值问题
核心问题分析
报错“Nullable object must have a value.”的本质是:直接访问了Nullable<T>类型的Value属性,但该对象当前为null。通常是因为Linq查询中未正确处理无记录或字段值为null的场景,强行读取了可空类型的Value。
前提确认
首先确保实体模型中,关卡时间字段是可空值类型,对应数据库允许空的字段:
public class UserLevelPlayRecord { public int UserId { get; set; } public int LevelId { get; set; } public int? BestTime { get; set; } // 必须声明为int?,不能是int }
可行解决方案
方案1:Linq查询中直接用空合并运算符(EF Core支持)
在Select阶段直接处理可空值,配合DefaultIfEmpty确保无记录时也返回默认值:
int thisUserBestTime = dbContext.UserLevelPlayRecords .Where(r => r.UserId == currentUserId && r.LevelId == targetLevelId) .Select(r => r.BestTime ?? -1) .DefaultIfEmpty(-1) .First();
不管是无匹配记录,还是有记录但BestTime为null,最终都会返回-1。
方案2:先查询实体再内存中处理
把数据拉到内存后再做空判断,逻辑更直观,也避免Linq to Entities的转换限制:
var userRecord = dbContext.UserLevelPlayRecords .FirstOrDefault(r => r.UserId == currentUserId && r.LevelId == targetLevelId); int thisUserBestTime = userRecord?.BestTime ?? -1;
方案3:使用可空类型自带的GetValueOrDefault方法
利用GetValueOrDefault直接指定默认值,同样支持EF Core转换:
int thisUserBestTime = dbContext.UserLevelPlayRecords .Where(r => r.UserId == currentUserId && r.LevelId == targetLevelId) .Select(r => r.BestTime.GetValueOrDefault(-1)) .DefaultIfEmpty(-1) .First();
错误写法示例(避坑)
以下写法会直接触发异常,请勿使用:
// 错误:无记录时FirstOrDefault返回null,访问.Value直接抛出异常 int thisUserBestTime = dbContext.UserLevelPlayRecords .Where(r => r.UserId == currentUserId && r.LevelId == targetLevelId) .Select(r => r.BestTime.Value) .FirstOrDefault() ?? -1;
内容的提问来源于stack exchange,提问作者Alex Ibrahim Ojea
相关产品推荐
相关产品推荐

