C#+MySQL库存系统搜索异常:检索数据与预期不符
问题分析与修复方案
核心问题点
dr.Read()导致的数据丢失
调用dr.Read()后,DataReader的指针会移动到第一条记录,后续dt.Load(dr)只能读取剩余的记录。如果查询结果只有1条记录,dt.Load会加载空数据,导致DataGridView显示为空,和实际结果不符。Int字段
LIKE查询的隐式转换风险Transaction_No和Cust_No是int类型,直接用LIKE查询时MySQL会自动做隐式类型转换,可能出现意想不到的匹配逻辑。加上如果filter参数被误传入Trans_Date(比如UI层传参错误),就会出现你遇到的"输入数字匹配到日期记录"的问题。全局变量的潜在干扰
使用全局的conString和cmd变量,很容易被其他代码篡改,导致执行的查询和预期不一致。
修复后的代码
// 搜索交易记录 public void searchTransaction(DataGridView table, string searchValue, string filterColumn) { // 校验筛选字段,仅允许指定的两个字段,防止误传或SQL注入 var allowedColumns = new[] { "Transaction_No", "Cust_No" }; if (!allowedColumns.Contains(filterColumn)) { MessageBox.Show("无效的筛选字段"); table.DataSource = null; return; } // 构造查询语句,显式将int字段转为字符串后进行LIKE匹配 string query = $"SELECT * FROM tbl_transactionhistory WHERE CAST({filterColumn} AS CHAR) LIKE @SearchValue"; // 使用using自动管理连接和命令对象的生命周期 using (var conn = connect()) { try { conn.Open(); using (var cmd = new MySqlCommand(query, conn)) { // 添加参数,避免SQL注入,同时确保匹配模式正确 cmd.Parameters.AddWithValue("@SearchValue", $"%{searchValue}%"); // 直接加载DataReader到DataTable,无需提前调用Read() DataTable dt = new DataTable(); dt.Load(cmd.ExecuteReader()); // 根据结果是否为空设置数据源 table.DataSource = dt.Rows.Count > 0 ? dt : null; } } catch (MySqlException ex) { MessageBox.Show($"数据库错误:{ex.Message}"); table.DataSource = null; } } }
关键修复说明
- 移除
dr.Read():DataTable.Load()会自动遍历整个DataReader读取所有数据,无需提前调用Read(),避免数据丢失。 - 添加字段校验:拦截误传的筛选字段(比如
Trans_Date),直接提示错误,从根源解决"匹配到日期记录"的问题。 - 显式类型转换:用
CAST({filterColumn} AS CHAR)把int字段转为字符串,明确匹配逻辑,避免MySQL隐式转换带来的异常。 - 使用
using语句:替代全局变量,确保数据库连接、命令对象被正确释放,同时避免被其他代码篡改。
额外排查建议
如果之前确实出现了匹配Trans_Date的情况,检查UI层的筛选字段选择逻辑(比如下拉框的绑定值),确认是否不小心将Trans_Date传给了filter参数。
内容的提问来源于stack exchange,提问作者siyel
相关产品推荐
相关产品推荐

