VB.NET+MS Access ATM系统转账后数据库余额未更新求助
问题分析与修复方案
你的代码存在多个导致数据库余额未更新的问题,以下是具体问题点和修复后的代码:
核心问题点
maxrows未初始化:循环条件i <> maxrows + 1因maxrows默认值为0,导致遍历逻辑异常,可能无法定位到目标账户行。- 字符串与数值直接运算:
txtSendAmount.Text是字符串类型,直接与数值类型的余额加减会引发类型转换错误,导致计算无效。 - 循环逻辑缺陷:找到转入账户后立即
Exit While,若转出账户在转入账户之后,转出操作永远不会执行。 - 缺少事务处理:转账是原子操作,必须保证转出、转入要么同时成功,要么同时失败,否则会出现数据不一致。
- 重复创建
OleDbCommandBuilder:每次修改行都新建实例,可能导致DataAdapter的UpdateCommand生成异常。 - 数据表无主键:
OleDbCommandBuilder需要数据表有主键(如ACCNO字段)才能生成有效的更新命令,这是数据库未更新的常见根源。
修复后的代码
' 先验证并转换转账金额为数值类型 Dim transferAmount As Decimal If Not Decimal.TryParse(txtSendAmount.Text, transferAmount) Then MsgBox("请输入有效的数字金额!") Return End If ' 使用事务确保转账原子性 Using conn As New OleDb.OleDbConnection(da.SelectCommand.Connection.ConnectionString) conn.Open() Dim transaction As OleDb.OleDbTransaction = conn.BeginTransaction() Try ' 为DataAdapter绑定事务 da.SelectCommand.Transaction = transaction ' 仅创建一次CommandBuilder,生成UpdateCommand Dim cb As New OleDb.OleDbCommandBuilder(da) Dim isTransferOutFound As Boolean = False Dim isTransferInFound As Boolean = False ' 遍历数据表,处理转出和转入账户 For Each row As DataRow In ds.Tables("G1 FINALS LOGIN CREATE").Rows ' 处理转出账户 If row("ACCNO").ToString().Trim() = lblAccno.Text.Trim() Then Dim currentBalance As Decimal = Convert.ToDecimal(row("BALANCE")) row("BALANCE") = currentBalance - transferAmount isTransferOutFound = True End If ' 处理转入账户 If row("ACCNO").ToString().Trim() = txtboxRecAccno.Text.Trim() Then Dim currentBalance As Decimal = Convert.ToDecimal(row("BALANCE")) row("BALANCE") = currentBalance + transferAmount isTransferInFound = True End If Next ' 检查是否找到两个目标账户 If Not isTransferOutFound Or Not isTransferInFound Then MsgBox("转出账户或转入账户不存在!") transaction.Rollback() Return End If ' 一次性提交所有修改到数据库 da.Update(ds, "G1 FINALS LOGIN CREATE") transaction.Commit() MsgBox("转账成功!") Me.Close() Dashboard.Show() Catch ex As Exception ' 出错则回滚所有操作 transaction.Rollback() MsgBox("转账失败:" & ex.Message) End Try End Using
关键修复说明
- 金额类型验证:使用
Decimal.TryParse确保输入金额是有效数字,避免类型错误。 - 事务处理:通过
OleDbTransaction保证转账操作的原子性,任何一步出错都会回滚所有修改。 - 遍历逻辑优化:用
For Each替代While循环,避免索引越界和未初始化变量的问题。 - CommandBuilder复用:仅创建一次实例,确保
DataAdapter能正确生成更新命令。 - 账户存在校验:提前检查转出/转入账户是否存在,避免无效操作。
- 数据表主键要求:务必确保
G1 FINALS LOGIN CREATE表的ACCNO字段设置为主键,否则OleDbCommandBuilder无法生成有效的UpdateCommand,数据库将无法更新。
内容的提问来源于stack exchange,提问作者Vins Vince
相关产品推荐
相关产品推荐

