获取类型计数时LINQ查询抛出NullReferenceException问题求助
问题排查与解决方案
异常原因分析
从栈跟踪和代码逻辑来看,NullReferenceException是在执行Where条件中的Any方法时触发的,核心问题是查询过程中访问了未实例化的导航属性:
- 测试数据里的
Participant.ParticipantConnections集合可能为null - 集合中某个
ParticipantConnection的Connection属性未实例化 - Moq对EF Core的
Include链式调用模拟不完整,导致导航属性未被正确加载
具体解决步骤
1. 修复测试数据的完整性
确保ParticipantMockData.ListAllAsyncEntity()返回的测试数据满足:
- 每个
Participant的ParticipantConnections集合不为null(空集合也要实例化为new List<ParticipantConnection>()) - 集合内所有
ParticipantConnection的Connection属性已实例化,且Connection.FirstName、Connection.LastName不为null
示例修正后的测试数据构造:
public static List<Participant> ListAllAsyncEntity() { return new List<Participant> { new Participant { ParticipantConnections = new List<ParticipantConnection> { new ParticipantConnection { Connection = new Connection { FirstName = "Alice", LastName = "Doe" } } } // 填充其他必要属性 } }; }
2. 修正Moq对Repository的模拟逻辑
原代码仅模拟了AsNoTracking(false),但未处理后续的Include调用,导致导航属性未被加载。直接返回包含完整导航属性的内存IQueryable即可:
// 替换原测试代码中的mock构建部分 var participantList = ParticipantMockData.ListAllAsyncEntity(); var queryableParticipants = participantList.AsQueryable(); // 模拟AsNoTracking返回带完整导航属性的查询 _participantRepository.Setup(x => x.AsNoTracking(false)).Returns(queryableParticipants); // 若AsNoTracking是无参重载,改为: // _participantRepository.Setup(x => x.AsNoTracking()).Returns(queryableParticipants);
3. 优化Service代码增加空值防护
在查询条件中提前判断空值,避免运行时异常:
participantsList = participantsList.Where(x => x.ParticipantConnections != null && (x.ParticipantConnections.Any(y => y.Connection != null && y.Connection.FirstName != null && y.Connection.FirstName.ToLower().Contains(queryModel.RelatedConnection.ToLower())) || x.ParticipantConnections.Any(y => y.Connection != null && y.Connection.LastName != null && y.Connection.LastName.ToLower().Contains(queryModel.RelatedConnection.ToLower())) || x.ParticipantConnections.Any(y => y.Connection != null && y.Connection.FirstName != null && y.Connection.LastName != null && (y.Connection.FirstName.ToLower() + y.Connection.LastName.ToLower()).Contains(queryModel.RelatedConnection.ToLower())) || x.ParticipantConnections.Any(y => y.Connection != null && y.Connection.FirstName != null && y.Connection.LastName != null && (y.Connection.FirstName.ToLower() + " " + y.Connection.LastName.ToLower()).Contains(queryModel.RelatedConnection.ToLower())) ) );
也可以用空条件运算符简化:
participantsList = participantsList.Where(x => x.ParticipantConnections?.Any(y => y.Connection?.FirstName?.ToLower().Contains(queryModel.RelatedConnection.ToLower()) == true) == true || x.ParticipantConnections?.Any(y => y.Connection?.LastName?.ToLower().Contains(queryModel.RelatedConnection.ToLower()) == true) == true || // 其他条件同理 );
内容的提问来源于stack exchange,提问作者hanushi-thana
相关产品推荐
相关产品推荐

