ATM系统数据库余额更新问题:如何存入新增存款并更新余额
解决ATM系统存款余额更新至数据库的问题
现有代码的核心问题
- 方法名不匹配:
updateSaldo方法中调用了不存在的getDbSaldo,实际应为getDbUpdate。 - SQL执行方式错误:
UPDATE属于数据修改操作,不应使用ExecuteReader(用于读取查询结果),需改用ExecuteNonQuery或ExecuteScalar。 - SQL注入风险:直接拼接字符串生成SQL语句,存在严重安全漏洞。
- 并发更新隐患:先查旧余额、再计算新余额后更新的逻辑,在多线程/并发场景下可能导致余额计算错误。
修正后的实现方案
1. 优化余额更新逻辑(数据库端直接累加)
推荐在数据库层面直接完成余额累加,避免先查后改的并发问题,同时简化代码:
private static decimal updateSaldo(string numeroCartao, string pin, decimal deposit) { // 直接在SQL中执行余额累加,同时返回更新后的余额 string query = @"UPDATE atmbd.atm SET Balance = Balance + @Deposit WHERE Pin = @Pin AND CardNumber = @CardNumber; SELECT Balance FROM atmbd.atm WHERE Pin = @Pin AND CardNumber = @CardNumber;"; using (var cn = new SqlConnection("Data Source=MAD-PC-023;Database=atmbd;Trusted_Connection=True;")) { cn.Open(); using (var cmd = new SqlCommand(query, cn)) { // 参数化查询,彻底避免SQL注入 cmd.Parameters.AddWithValue("@Deposit", deposit); cmd.Parameters.AddWithValue("@Pin", pin); cmd.Parameters.AddWithValue("@CardNumber", numeroCartao); // 执行查询并返回更新后的余额 return (decimal)cmd.ExecuteScalar(); } } }
2. 调整主逻辑代码
无需先查询旧余额再计算,直接传入存款金额调用更新方法即可:
decimal deposit = 0; Console.WriteLine("\n Quanto deseja depositar ?"); // 询问客户存款金额 // 添加输入验证,避免非法输入导致程序崩溃 if (!decimal.TryParse(Console.ReadLine(), out deposit) || deposit <= 0) { Console.WriteLine("Valor de depósito inválido!"); return; } decimal saldoAtual = updateSaldo(debitCard, pin, deposit); Console.WriteLine("\n O seu saldo atual é de " + saldoAtual + " euro(s) \n Depósito: " + deposit + " euro(s)");
3. 关键改进点说明
- 参数化查询:用
@参数名替代字符串拼接,彻底杜绝SQL注入风险。 - 数据库端累加:
Balance = Balance + @Deposit直接在数据库中完成更新,避免并发场景下的余额覆盖问题。 - 输入验证:通过
decimal.TryParse确保存款金额合法,提升程序稳定性。 - 直接返回结果:用
ExecuteScalar获取更新后的余额,无需额外查询操作。
内容的提问来源于stack exchange,提问作者user20571251
相关产品推荐
相关产品推荐

