You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 07:39:51