VB.NET中DataGridView结合ComboBox更新数据库及筛选失效问题求助
问题解决与优化方案
1. 修复“Parameters不是String的成员”错误
这个错误的核心原因是你直接对字符串类型的SQL语句调用Parameters属性——字符串本身没有这个成员。正确做法是创建OleDbCommand对象并添加参数,再传递给数据适配器。
2. 重构DatabaseManager类(最优实现)
原类存在资源泄漏风险、线程使用不合理、参数化查询支持缺失等问题。重构后加入using语句管理资源,移除不必要的线程,完善参数化查询支持:
Imports System.Data.OleDb Imports System.Configuration Friend Class DatabaseManager Private ReadOnly connectionString As String = ConfigurationManager.ConnectionStrings("ConnStr").ConnectionString Public Function FillData(ByVal sql As String, Optional parameters As IEnumerable(Of OleDbParameter) = Nothing) As DataTable If String.IsNullOrWhiteSpace(sql) Then Throw New ArgumentException("SQL语句不能为空") End If Dim dt As New DataTable() ' 使用using自动释放连接、适配器等资源,无需手动管理 Using conn As New OleDbConnection(connectionString), adapter As New OleDbDataAdapter(sql, conn) ' 添加查询参数(如果有) If parameters IsNot Nothing Then adapter.SelectCommand.Parameters.AddRange(parameters.ToArray()) End If conn.Open() adapter.Fill(dt) ' 直接生成更新/插入/删除命令,无需额外线程 Dim builder As New OleDbCommandBuilder(adapter) adapter.InsertCommand = builder.GetInsertCommand() adapter.UpdateCommand = builder.GetUpdateCommand() adapter.DeleteCommand = builder.GetDeleteCommand() ' 将适配器存入DataTable的扩展属性,确保更新时匹配正确的命令 dt.ExtendedProperties.Add("DataAdapter", adapter) End Using Return dt End Function Public Function UpdateData(ByVal dt As DataTable) As Integer If Not dt.ExtendedProperties.ContainsKey("DataAdapter") Then Throw New InvalidOperationException("未找到对应的数据适配器,请先通过FillData加载数据") End If Dim adapter As OleDbDataAdapter = DirectCast(dt.ExtendedProperties("DataAdapter"), OleDbDataAdapter) Return adapter.Update(dt) End Function End Class
3. 修正LoadData方法实现筛选功能
修改窗体中的LoadData方法,正确构建参数化查询以实现筛选:
Private dtData As DataTable Private db As New DatabaseManager() Private Sub LoadData() If ComboBox1.SelectedIndex > -1 Then ' 创建参数并指定类型,避免隐式类型转换问题 Dim invNoParam As New OleDbParameter("@INVNO", OleDbType.VarChar) invNoParam.Value = CStr(ComboBox1.SelectedValue) ' 执行带参数的筛选查询 dtData = db.FillData("SELECT * FROM DEMOTABLEPRODUCT WHERE INVNO = @INVNO", {invNoParam}) gvMain.DataSource = dtData Else ' 未选择项时加载全部数据 dtData = db.FillData("SELECT * FROM DEMOTABLEPRODUCT") gvMain.DataSource = dtData End If End Sub
4. 关于using语句的必要性
必须使用using语句,原因如下:
- 数据库连接、OleDbCommand、OleDbDataAdapter都实现了
IDisposable接口,using块会自动调用Dispose()释放资源,避免连接池耗尽、内存泄漏。 - 即使代码执行中发生异常,using块也会自动关闭数据库连接,无需手动判断连接状态。
5. 其他优化点
- 移除原类中的全局
conn、adapter、threadHelper,避免多线程操作时的冲突和资源泄漏。 - 使用DataTable的
ExtendedProperties存储对应适配器,确保更新操作能匹配正确的SQL命令。 - 增加未选择ComboBox项时的默认逻辑,加载全部数据提升用户体验。
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

