C# LINQ查询存在匹配项却报Sequence contains no element错误
问题排查结论
已确认正常的前置运行环节:
- 数据库连接工作正常
- 目标数据表可正常获取
- 类定义中对应字段可正常匹配找到
- 可正常取出待比对项的MAC地址用于匹配逻辑
报错核心原因
出现的两个报错本质是同一问题导致的连锁反应,"Sequence contains no element"是完全误导性的表象异常,不是真的不存在匹配项:
- 反射取值的类型比较逻辑错误
FieldInfo.GetValue()方法的返回值固定为object类型:- 对比字符串类型字段时,因为字符串是引用类型且重载了
==运算符,加上硬编码字符串的内部留用机制,刚好让==判断命中引用相等,所以看起来查询正常 - 对比
bool、DateTime这类值类型字段时,反射拿到的是装箱后的object实例,直接和传入的值类型用==比较会触发类型不匹配错误,也就是看到的"无法将object与bool类型进行比较",这才是真实的原始异常 - 由于用了
dynamic作为查询参数类型,运行时绑定器在部分执行上下文下会包装、吞掉原始类型异常,导致LINQ的where条件没有正确执行、直接返回空序列,此时调用First()方法就会抛出"Sequence contains no element"的错误,完全掩盖了真实问题。
- 对比字符串类型字段时,因为字符串是引用类型且重载了
- LINQ方法选用不当
使用的First()方法在查询结果为空时会直接抛出异常,和方法设计中"查不到返回null"的逻辑不符,就算真的不存在匹配项也会触发非预期报错。
调试参考截图:
修复方案
只需要修改GetOneLocal方法的逻辑即可,不需要改动其他业务代码:
- 将参数类型从
dynamic改为object,避免动态绑定带来的异常包装问题 - 比较字段值前,先将传入参数转换为字段对应的实际类型,再做相等判断
- 将
First()替换为FirstOrDefault(),无匹配项时直接返回默认值(引用类型默认就是null),符合方法设计逻辑
修复后的方法代码如下:
public static T GetOneLocal<T>(string fieldName, object value) where T : InheritedClass { FieldInfo fieldFound = typeof(T).GetField(fieldName); if (fieldFound == null) { Console.Write("field not found into class\n"); return null; } try { return GetLocalTable<T>() .Values .FirstOrDefault(item => { object fieldValue = fieldFound.GetValue(item); // 处理空值场景 if (fieldValue == null && value == null) return true; if (fieldValue == null || value == null) return false; // 类型统一后再做相等比较 var convertedTarget = Convert.ChangeType(value, fieldFound.FieldType); return fieldValue.Equals(convertedTarget); }); } catch (Exception e) { Console.Write("query failed with error : " + e.Message + "\n"); return null; } }
额外优化提示
当前代码中typeof(T).GetField(fieldName)默认只查找公共实例字段,如果后续类中新增了非公共字段、或者属性而非字段,会出现找不到成员的问题,可以根据实际需求调整绑定标志。
内容的提问来源于stack exchange,提问作者Matheus_UG
相关产品推荐
相关产品推荐


