.NET Framework 4.x中LINQ查询无匹配记录时FirstOrDefault()返回0而非null导致逻辑异常的问题排查
.NET Framework 4.x中LINQ查询无匹配记录时FirstOrDefault()返回0而非null导致逻辑异常的问题排查
嗨,我来帮你拆解下这个问题的根源和解决办法~
问题一:你的if (query == null)判断完全无效
LINQ的Where和Select方法返回的是IQueryable<decimal>对象,哪怕没有匹配的数据库记录,这个对象本身也永远不会是null——它只是一个待执行的查询表达式,不是查询结果。所以这个分支代码永远不会被触发,这是第一个逻辑漏洞。
问题二:值类型的FirstOrDefault()默认返回0.0而非null
你的查询最终Select的是s.multiplier,对应数据库里的DECIMAL(8,2),在.NET中映射为值类型decimal。而值类型的特性是不能为null,所以当调用FirstOrDefault()时:
- 如果查询到匹配记录,返回第一个记录的
multiplier值; - 如果没有匹配记录,返回
decimal类型的默认值——也就是0.0m。
这就导致不管有没有匹配记录,你都会执行乘法逻辑,因为query.FirstOrDefault()永远不会是null,无匹配时只会返回0.0,自然会触发else分支。
修复方案(推荐第一种,效率更高)
方案1:将查询结果转为可空decimal类型
把Select的结果转为decimal?(可空值类型),这样无匹配时FirstOrDefault()会返回null,就能正确区分“无记录”和“值为0.0”的情况:
// 修改查询,将multiplier转为可空类型 var query = context.wp_cli_card_jf_sub .Where(s => s.cli_card_jf_list_no == deserializedDMLparModels.Clicardjfretno && s.com_md_code == Userid && s.prod_no == detail.Prodno) .Select(s => (decimal?)s.multiplier); // 获取结果并判断 var multiplier = query.FirstOrDefault(); if (multiplier == null) { wjf.cli_card_jf_num = Convert.ToDecimal(detail.Clicardjfnum); } else { // 使用.Value获取可空类型的实际值 wjf.cli_card_jf_num = Convert.ToDecimal(detail.Clicardjfnum) * multiplier.Value; }
方案2:先判断是否存在记录再取值
这种方式会执行两次数据库查询(一次Any(),一次FirstOrDefault()),效率略低,但逻辑更直观:
// 先检查是否存在匹配记录 var hasMatch = context.wp_cli_card_jf_sub .Any(s => s.cli_card_jf_list_no == deserializedDMLparModels.Clicardjfretno && s.com_md_code == Userid && s.prod_no == detail.Prodno); if (!hasMatch) { wjf.cli_card_jf_num = Convert.ToDecimal(detail.Clicardjfnum); } else { var multiplier = context.wp_cli_card_jf_sub .Where(s => s.cli_card_jf_list_no == deserializedDMLparModels.Clicardjfretno && s.com_md_code == Userid && s.prod_no == detail.Prodno) .Select(s => s.multiplier) .FirstOrDefault(); wjf.cli_card_jf_num = Convert.ToDecimal(detail.Clicardjfnum) * multiplier; }
补充说明
记住一个关键知识点:.NET中值类型(如int、decimal、DateTime等)的默认值不是null,只有引用类型和可空值类型才能表示“不存在”的状态。当你需要用FirstOrDefault()区分“无结果”和“默认值”时,一定要把值类型转为可空版本~
内容来源于stack exchange
相关产品推荐
相关产品推荐

