C#中DataGridView仅显示列头不加载数据问题排查
问题排查:DataGridView仅显示列头无数据
问题背景
在C# WinForms项目中,尝试通过DataGridView展示SQL Server存储过程TechnicalRejects的返回数据,但仅能看到列头,无法加载具体数据。已通过EXEC命令验证存储过程可正常返回数据,问题出在代码逻辑中。
相关代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Data.SqlClient; namespace RonnaForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public class columnTitle { public int Id { get; set; } public string Site { get; set; } public string ProductCode { get; set; } public string ProductName { get; set; } public string PrimaryRejectionReason { get; set; } public string SecondaryRejectionReason { get; set; } public string AdditionalComments { get; set; } } private void Form1_Load(object sender, EventArgs e) { DataTable Dtable = new DataTable(); //创建一个名为Dtable的新DataTable try { // 连接SQL Server数据库 using (var con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;")) //创建与Test_Playground数据库的连接 // 获取目标存储过程 using (var cmd = new SqlCommand("TechnicalRejects", con)) // 用于填充列数据 using (var da = new SqlDataAdapter(cmd)) { cmd.Parameters.AddWithValue("@Site", CBox1.Text.ToString()); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.Text.ToString()); cmd.CommandType = CommandType.StoredProcedure; // 填充DataTable da.Fill(Dtable); } DataGridView.DataSource = Dtable; } catch (Exception ex) { MessageBox.Show("发生错误:" + ex.Message); } // 为第一个下拉框添加选项 CBox1.Text = "All"; CBox1.Items.Add("Town1"); CBox1.Items.Add("Town2"); CBox1.Items.Add("Town3"); CBox1.Items.Add("Town4"); CBox1.Items.Add("Town5"); // 默认选中"All" CBox1.SelectedIndex = 0; // 为第二个下拉框添加选项 CBox2.Text = "All"; CBox2.Items.Add("All"); CBox2.Items.Add("Label Issue"); CBox2.Items.Add("Out of Specification"); CBox2.Items.Add("Contamination"); CBox2.Items.Add("Damaged"); CBox2.Items.Add("Order Administration"); CBox2.Items.Add("Other"); // 默认选中"All" CBox2.SelectedIndex = 0; } private void CBoxRejection_SelectedIndexChanged(object sender, EventArgs e) { // 此为CBox1,用于选择站点 DataTable Otable = new DataTable(); try { SqlConnection con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;"); SqlCommand cmd = new SqlCommand("TechnicalRejects", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@Site", CBox1.Text.ToString()); SqlDataAdapter dga = new SqlDataAdapter(); dga.SelectCommand = cmd; dga.Fill(Otable); DataGridView.DataSource = Otable; } catch (Exception ex) { MessageBox.Show("搜索站点时发生错误:" + ex.Message); } } private void CBox2_SelectedIndexChanged(object sender, EventArgs e) { // 此为CBox2,用于选择拒收原因 DataTable Otable = new DataTable(); SqlConnection con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;"); SqlCommand cmd = new SqlCommand("TechnicalRejects", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@Site", CBox1.Text.ToString()); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.Text.ToString()); SqlDataAdapter dga = new SqlDataAdapter(); dga.SelectCommand = cmd; dga.Fill(Otable); DataGridView.DataSource = Otable; } private void btnSearch_Click(object sender, EventArgs e) { // 创建用于存储结果的新DataTable DataTable Dtable = new DataTable(); try { // 指定数据库地址并声明调用存储过程 SqlConnection con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;"); SqlCommand cmd = new SqlCommand("TechnicalRejects", con); cmd.CommandType = CommandType.StoredProcedure; // 添加搜索筛选参数 cmd.Parameters.AddWithValue("@Site", CBox1.SelectedItem.ToString()); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.SelectedItem.ToString()); SqlDataAdapter dga = new SqlDataAdapter(cmd); dga.Fill(Dtable); // 用搜索结果填充DataTable // 将DataTable绑定到DataGridView DataGridView.DataSource = Dtable; } catch (Exception ex) { // 处理错误 MessageBox.Show("搜索时发生错误:" + ex.Message); } } private void btnExit_Click(object sender, EventArgs e) { Application.Exit(); } } }
问题原因及修复方案
1. Form1_Load方法中下拉框初始化顺序错误
问题:调用存储过程的逻辑在下拉框初始化之前执行,此时CBox1.Text和CBox2.Text为空字符串,传递空参数给存储过程导致返回空结果。
修复:将下拉框初始化代码移到存储过程调用之前:
private void Form1_Load(object sender, EventArgs e) { // 先初始化下拉框 CBox1.Items.Add("All"); CBox1.Items.Add("Town1"); CBox1.Items.Add("Town2"); CBox1.Items.Add("Town3"); CBox1.Items.Add("Town4"); CBox1.Items.Add("Town5"); CBox1.SelectedIndex = 0; CBox2.Items.Add("All"); CBox2.Items.Add("Label Issue"); CBox2.Items.Add("Out of Specification"); CBox2.Items.Add("Contamination"); CBox2.Items.Add("Damaged"); CBox2.Items.Add("Order Administration"); CBox2.Items.Add("Other"); CBox2.SelectedIndex = 0; DataTable Dtable = new DataTable(); try { using (var con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;")) using (var cmd = new SqlCommand("TechnicalRejects", con)) using (var da = new SqlDataAdapter(cmd)) { cmd.Parameters.AddWithValue("@Site", CBox1.Text); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.Text); cmd.CommandType = CommandType.StoredProcedure; da.Fill(Dtable); } DataGridView.DataSource = Dtable; } catch (Exception ex) { MessageBox.Show("发生错误:" + ex.Message); } }
2. CBoxRejection_SelectedIndexChanged事件参数不完整
问题:该事件处理CBox1的选择变更,但调用存储过程时仅传递了@Site参数,未传递@PrimaryRejectionReason,若存储过程依赖两个参数返回数据,会导致结果为空。
修复:补充参数传递并规范资源释放:
private void CBoxRejection_SelectedIndexChanged(object sender, EventArgs e) { DataTable Otable = new DataTable(); try { using (SqlConnection con = new SqlConnection("Data Source=ffgsqltest2;Initial Catalog=Test_Playground;Integrated Security=True;")) using (SqlCommand cmd = new SqlCommand("TechnicalRejects", con)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@Site", CBox1.Text); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.Text); using (SqlDataAdapter dga = new SqlDataAdapter(cmd)) { dga.Fill(Otable); DataGridView.DataSource = Otable; } } } catch (Exception ex) { MessageBox.Show("搜索站点时发生错误:" + ex.Message); } }
3. 数据库资源未正确释放
问题:CBox2_SelectedIndexChanged等方法中,SqlConnection、SqlCommand未用using包裹,可能导致资源泄漏,影响数据读取稳定性。
修复:所有数据库操作对象均用using语句包裹,确保资源自动释放(参考上面CBoxRejection_SelectedIndexChanged的修复代码)。
4. btnSearch中参数获取的潜在空引用问题
问题:使用CBox1.SelectedItem.ToString(),若下拉框未选中任何项(极端场景)会抛出NullReferenceException。
修复:改用CBox1.Text更稳妥:
cmd.Parameters.AddWithValue("@Site", CBox1.Text); cmd.Parameters.AddWithValue("@PrimaryRejectionReason", CBox2.Text);
额外调试建议
- 填充DataTable后,可通过
Dtable.Rows.Count查看是否有数据,快速定位是参数问题还是存储过程返回问题。 - 确认存储过程对"All"参数的处理逻辑,比如是否通过
WHERE (@Site = 'All' OR Site = @Site)实现全量查询。
内容的提问来源于stack exchange,提问作者Ronan Cunningham
相关产品推荐
相关产品推荐

