C# WinForms切换SQLite数据库后DataGridView仍显示旧数据求助
解决WinForms切换公司后DataGridView显示旧数据的问题
问题诊断
- 静态连接字符串固化:
AccessToDatabaseComp中的dbPathcomp和conStringComp是静态字段,类加载时就固定了初始数据库路径,切换公司后不会重新计算,导致始终连接旧数据库。 - 静态SQLite连接未重置:静态
sqlite连接实例一旦创建,切换数据库时不会销毁,仍然指向旧数据库文件。 - 连接管理逻辑错误:
sqliteconComp方法中,如果连接已打开会直接关闭,后续操作会使用无效的关闭连接,导致数据读取异常。 - 查询条件逻辑矛盾:
ViewSearch中的if (string.IsNullOrEmpty(search) && !string.IsNullOrEmpty(search))永远为假,空搜索时也会执行模糊查询逻辑。
解决方案
1. 重构数据访问类,移除静态依赖
修改数据访问类,每次获取连接时动态读取当前数据库路径,确保切换公司后连接新数据库:
public class AccessToDatabaseComp { // 动态获取最新的连接字符串 private static string GetConnectionString() { string dbPath = Application.StartupPath + "\\" + frmMain.Instance.lblDBFile.Text; return $"Data Source={dbPath};Version=3;"; } private static SQLiteConnection _sqliteConn; public static SQLiteConnection GetConnection() { // 销毁旧连接,避免残留 if (_sqliteConn != null) { if (_sqliteConn.State == ConnectionState.Open) _sqliteConn.Close(); _sqliteConn.Dispose(); _sqliteConn = null; } // 创建新连接并打开 _sqliteConn = new SQLiteConnection(GetConnectionString()); _sqliteConn.Open(); return _sqliteConn; } // 重构retrieve方法,使用using管理连接 public static DataSet Retrieve(string query) { try { using (var conn = GetConnection()) { using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, conn)) { DataSet ds = new DataSet(); adapter.Fill(ds); return ds; } } } catch { return null; } } // 重构insert/update/delete方法,统一使用using管理连接 public static bool Insert(string query) { try { using (var conn = GetConnection()) { using (SQLiteCommand cmd = new SQLiteCommand(query, conn)) { int rows = cmd.ExecuteNonQuery(); return rows > 0; } } } catch { return false; } } // update和delete方法参照insert修改... }
2. 修复ViewSearch方法的逻辑错误
修正矛盾的查询条件,统一数据加载逻辑:
private void ViewSearch(string search) { try { string query = string.Empty; // 修正条件:空搜索执行全量查询,否则执行模糊查询 if (string.IsNullOrEmpty(search)) { query = "Select * from tblAccount"; } else { query = "Select * from tblAccount where AccountName Like '%" + search + "%'"; } // 加载新数据 var ds = AccessToDatabaseComp.Retrieve(query); dgvAccountView.AutoGenerateColumns = false; if (ds != null && ds.Tables[0].Rows.Count > 0) { dgvAccountView.DataSource = ds.Tables[0]; // 列配置保持不变 dgvAccountView.Columns[0].HeaderText = "Account ID"; dgvAccountView.Columns[0].Width = 50; dgvAccountView.Columns[0].DataPropertyName = "AccountID"; dgvAccountView.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft; dgvAccountView.Columns[1].HeaderText = "Account Name"; dgvAccountView.Columns[1].Width = 500; dgvAccountView.Columns[1].DataPropertyName = "AccountName"; dgvAccountView.Columns[1].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft; dgvAccountView.Columns[2].HeaderText = "Credit"; dgvAccountView.Columns[2].Width = 150; dgvAccountView.Columns[2].DataPropertyName = "Credit"; dgvAccountView.Columns[2].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight; dgvAccountView.Columns[3].HeaderText = "Debit"; dgvAccountView.Columns[3].Width = 150; dgvAccountView.Columns[3].DataPropertyName = "Debit"; dgvAccountView.Columns[3].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight; } else { dgvAccountView.DataSource = null; } } catch (Exception ex) { // 添加异常提示,方便排查问题 MessageBox.Show($"加载数据失败:{ex.Message}"); } }
3. 切换公司时强制刷新数据
在切换公司的逻辑中,更新数据库文件名后立即调用ViewSearch刷新DataGridView:
// 示例:切换公司的方法 private void SwitchCompany(string newDbFileName) { // 更新当前数据库文件名 frmMain.Instance.lblDBFile.Text = newDbFileName; // 刷新账户模块数据 ViewSearch(string.Empty); }
额外优化建议
- 防止SQL注入:当前模糊查询直接拼接字符串存在风险,改用参数化查询:
// 在Retrieve方法中修改查询逻辑 public static DataSet Retrieve(string search) { try { string query = string.IsNullOrEmpty(search) ? "Select * from tblAccount" : "Select * from tblAccount where AccountName Like @Search"; using (var conn = GetConnection()) { using (SQLiteCommand cmd = new SQLiteCommand(query, conn)) { if (!string.IsNullOrEmpty(search)) { cmd.Parameters.AddWithValue("@Search", "%" + search + "%"); } using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd)) { DataSet ds = new DataSet(); adapter.Fill(ds); return ds; } } } } catch { return null; } } - 使用BindingSource管理数据源:通过
BindingSource作为中间层,更方便数据刷新:private BindingSource _bs = new BindingSource(); // 加载数据时 _bs.DataSource = ds.Tables[0]; dgvAccountView.DataSource = _bs; // 刷新时调用 _bs.ResetBindings(false);
内容的提问来源于stack exchange,提问作者wasim khan
相关产品推荐
相关产品推荐

