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

C# WPF SQL查询绑定DataGrid抛出NullReferenceException异常

问题根因

你碰到的NullReferenceException本质是DataGrid绑定的数据源类型变了,硬转类型失败返回null,直接访问null的属性自然报错:

  • 用db.Issue_Note.ToList()绑定时,每一行的数据源都是强类型Issue_Note实体,SelectedItem as Issue_Note转换正常,所以不会出问题
  • 点搜索之后你绑定的是DataTable.DefaultView,这时候SelectedItem实际是DataRowView类型,根本不是Issue_Note,as转换直接返回null
  • 你构造函数里虽然写了SqlQuery的绑定代码,但下一行马上又用db.Issue_Note.ToList()覆盖了,所以初始化阶段不会报错,只要执行过搜索就会触发异常

修复方案

1. 兼容两种数据源类型的取值逻辑

修改LoadGrid方法,不要硬转Issue_Note,先判空再根据实际数据源类型取出库单号:

public void LoadGrid()
{
    dt = new DataTable();
    string isnNo = string.Empty;
    
    // 先处理未选中行的边界情况
    if (PnlISNDetails_SK.datagrid.SelectedItem == null)
    {
        MessageBox.Show("请先选择一条出库单记录");
        return;
    }

    // 分别适配强类型实体和DataTable两种数据源
    if (PnlISNDetails_SK.datagrid.SelectedItem is Issue_Note noteEntity)
    {
        isnNo = noteEntity.Issue_No;
    }
    else if (PnlISNDetails_SK.datagrid.SelectedItem is DataRowView rowView)
    {
        isnNo = rowView["Issue_No"].ToString();
    }

    if (string.IsNullOrWhiteSpace(isnNo))
    {
        MessageBox.Show("未获取到选中的出库单号");
        return;
    }

    addIssueNoteLogic = new AddIssueNoteLogic();
    addIssueNoteLogic.ViewISNDetails(isnNo).Fill(dt);
    dgItemsInISN.ItemsSource = dt.DefaultView;
}

2. 修复EF原生SQL查询的映射问题

如果要继续用SqlQuery<Issue_Note>返回强类型实体,要满足两个要求:

  • 查询返回的列名必须和Issue_Note实体的属性名完全匹配,大小写、拼写不能有偏差
  • 必须查询实体标注的主键列,否则EF实体跟踪逻辑会异常,容易出现属性值为null的问题
  • 构造函数里重复给ItemsSource赋值的冗余代码删掉,只保留需要的绑定逻辑即可

如果不想兼容两种数据源,做筛选时完全可以不用SqlDataAdapter填DataTable,直接用EF的参数化Where查询或者SqlQuery返回List<Issue_Note>绑定,全程用强类型实体,从根源上避免类型转换问题。

3. 必须修复SQL注入漏洞

你现在直接拼接用户输入到SQL语句的写法有严重的SQL注入风险,必须改成参数化查询,以按单号查询为例:

public SqlDataAdapter ViewISNFromISNNo(string searchText)
{
    con.Open();
    cmd = new SqlCommand();
    // 不要直接拼接searchText,用参数占位
    cmd.CommandText = "select * from Issue_Note where Issue_No like @searchKey";
    // 给参数传值
    cmd.Parameters.AddWithValue("@searchKey", $"%{searchText}%");
    cmd.Connection = con;
    da = new SqlDataAdapter(cmd);
    con.Close();
    return da;
}

其余按日期查询、查明细的方法都按这个逻辑改成参数化,不要直接拼接字符串,否则不仅容易被SQL注入攻击,还会频繁出现日期格式不匹配、特殊字符转义失败的问题。


额外优化建议
  • 数据库连接对象不要用全局共享实例,每次查询时新建SqlConnection,用完自动释放,否则很容易出现连接池占满、连接状态异常的问题
  • 所有实现了IDisposable的对象(SqlConnection、SqlCommand、SqlDataAdapter等)都包裹在using块中,自动释放资源,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:09:18