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

SQL左连接分组统计转LINQ后FirstOrDefault返回null报错解决

SQL转LINQ查询空引用报错解决方案

问题背景

需要将如下统计SQL转换为LINQ语句:

SELECT        
    dbo.Transactions.TypeRefID, 
    dbo.TransactionItems.ItemRefID, 
    SUM(dbo.TransactionItems.Quantity) AS Qty
FROM
    dbo.TransactionItems 
LEFT OUTER JOIN
    dbo.Transactions ON dbo.TransactionItems.TransactionRefID = dbo.Transactions.TransactionID
GROUP BY 
    dbo.Transactions.TypeRefID, dbo.TransactionItems.ItemRefID
HAVING        
    (dbo.Transactions.TypeRefID = 1) 
    AND (dbo.TransactionItems.ItemRefID = 5)

初始编写的LINQ实现代码如下:

var query = from t in db.Transaction
                        join i in db.TransactionItem on t.TransactionID equals i.TransactionRefID
                        where t.TypeRefID == 1 && i.ItemRefID == 5
                        group i by new
                        {
                            t.TypeRefID,
                            i.ItemRefID
                        } into g
                        select new
                        {
                            TypeRefID = g.Key.TypeRefID,
                            ItemRefID = g.Key.ItemRefID,
                            Quantity = g.Sum(q => q.Quantity)
                        };

运行时抛出System.Linq.Queryable.FirstOrDefault(...) returned null错误,调用逻辑如下,错误触发点为query.FirstOrDefault().Quantity.ToString():

if (query != null)
string qty = query.FirstOrDefault().Quantity.ToString();

问题原因&修复方案

报错来自两个核心问题:

  • 连接逻辑错误:原始SQL是TransactionItems左外连接Transactions,初始LINQ写反了主表,还使用了默认的内连接,和SQL逻辑不匹配,可能漏数据或者查询结果不符合预期。
  • 空值判断逻辑无效:query本身是IQueryable类型对象,只要声明就不会为null,写的if (query != null)完全没有防护作用。当数据库没有匹配的查询结果时,FirstOrDefault()会返回null,直接访问null对象的Quantity属性就会抛出空引用错误。

第一步:修正LINQ查询逻辑,对齐SQL的左外连接

var query = from i in db.TransactionItem
            // 实现TransactionItem左连接Transaction
            join t in db.Transaction on i.TransactionRefID equals t.TransactionID into joinRes
            from t in joinRes.DefaultIfEmpty()
            // 左连接后t可能为null,做空值兼容
            where (t == null ? 0 : t.TypeRefID) == 1 && i.ItemRefID == 5
            group i by new
            {
                TypeRefID = t == null ? 0 : t.TypeRefID,
                i.ItemRefID
            } into g
            select new
            {
                TypeRefID = g.Key.TypeRefID,
                ItemRefID = g.Key.ItemRefID,
                Quantity = g.Sum(q => q.Quantity)
            };

第二步:修正调用时的空值判断

不要直接链式访问FirstOrDefault()返回结果的属性,先判断返回值是否为null,同时给无匹配结果的场景设置默认值:

string qty = "0"; // 无匹配数据时的默认数量
var result = query.FirstOrDefault();
if (result != null)
{
    qty = result.Quantity.ToString();
}

内容的提问来源于stack exchange,提问作者Amiel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:06:19