.NET Framework4下用ADO.NET经典命令替换CommandBuilder的最优方案
性能问题根因
你遇到的慢是因为FbCommandBuilder调用GetInsertCommand/GetUpdateCommand/GetDeleteCommand时,会主动向Firebird数据库发起多次元数据查询,拉取表结构、主键约束、字段类型等信息才能动态生成SQL,VPN高延迟场景下,这部分额外的网络往返开销会被成倍放大,字段越多耗时越久。
最优替换方案
优先选择手动预配置DataAdapter命令的方案,这个方案改动最小、性能最优,不需要修改你原有对DataTable的计算逻辑,也不需要自己逐行判断行状态,还能复用DataAdapter的批量更新能力:
实现步骤
- 提前写好固定的增删改SQL,不用动态生成
- 手动给
FbDataAdapter的三个命令属性赋值,提前绑定参数和对应DataTable字段的映射 - 直接调用原有
wFbADA.Update(tbl)逻辑即可
代码示例
' 初始化连接和查询逻辑和原来一致 wConn = New FbConnection("...") wConn.Open() wCmd = New FbCommand("SELECT * FROM 你的表名", wConn) wCmd.CommandType = CommandType.Text wFbADA = New FbDataAdapter(wCmd) ' ===== 替换CommandBuilder的部分 开始===== ' 1. 预定义Insert命令,参数名和表字段一一对应,@前缀是Firebird参数规范 wFbADA.InsertCommand = New FbCommand("INSERT INTO 你的表名 (字段1,字段2,...字段100) VALUES (@字段1,@字段2,...@字段100)", wConn) ' 绑定参数和DataTable的字段映射,不用每次赋值 wFbADA.InsertCommand.Parameters.Add("@字段1", FbDbType.你字段的类型, 字段长度, "DataTable里对应的字段名") wFbADA.InsertCommand.Parameters.Add("@字段2", FbDbType.你字段的类型, 字段长度, "DataTable里对应的字段名") ' ... 剩下98个字段参数绑定,可写个小脚本批量生成,不用手敲 ' 2. 预定义Update命令,注意WHERE条件用主键定位行 wFbADA.UpdateCommand = New FbCommand("UPDATE 你的表名 SET 字段1=@字段1,字段2=@字段2,...字段100=@字段100 WHERE 主键字段=@主键字段", wConn) ' 同样绑定参数映射,主键参数的SourceVersion要设为Original,避免取修改后的值 wFbADA.UpdateCommand.Parameters.Add("@字段1", FbDbType.你字段的类型, 字段长度, "DataTable里对应的字段名") ' ... 其他字段参数 Dim pkParam = wFbADA.UpdateCommand.Parameters.Add("@主键字段", FbDbType.你主键类型, 主键长度, "主键字段名") pkParam.SourceVersion = DataRowVersion.Original ' 3. 预定义Delete命令,同样用主键定位 wFbADA.DeleteCommand = New FbCommand("DELETE FROM 你的表名 WHERE 主键字段=@主键字段", wConn) Dim delPkParam = wFbADA.DeleteCommand.Parameters.Add("@主键字段", FbDbType.你主键类型, 主键长度, "主键字段名") delPkParam.SourceVersion = DataRowVersion.Original ' ===== 替换CommandBuilder的部分 结束===== ' 后面的逻辑完全不用改 wFbADA.Fill(tbl) For Each rw In tbl.rows ' 原有的字段计算逻辑保留 Next ' 不用再调用CommandBuilder的方法,直接Update即可 wFbADA.Update(tbl)
可选补充优化
- 如果Firebird驱动支持批量更新,可设置
wFbADA.UpdateBatchSize = 100(数值按需调整),一次性提交多行更新,进一步减少VPN下的网络往返次数 - 所有更新操作包入
FbTransaction,避免单次提交的事务开销,同时保证数据一致性 - 如果你确实需要逐行控制更新逻辑,才用你想到的遍历RowState的方案,注意提前创建好三个命令对象、复用参数,循环内只修改参数值再执行,不要每次循环都新建命令对象
内容的提问来源于stack exchange,提问作者mrapi
相关产品推荐
相关产品推荐

