如何修改C#代码以显示指定卡号的所有数据库交易记录?
修改C#代码以返回指定卡号的所有交易记录
原代码存在的核心问题
- 循环读取记录时,每读取一条就直接用
return退出方法,导致只能返回第一条匹配的交易记录 - 直接拼接SQL字符串,存在SQL注入风险,恶意输入可能破坏数据库或窃取数据
- 判断字段为空的逻辑错误:数据库中的
NULL在SqlDataReader中对应DBNull,直接调用GetString()会抛出异常,不能用== null判断
修改后的完整代码
private static string extratoOperacao(string numeroCartao) { // 改用参数化查询传递卡号,避免SQL注入 return getExtrato(numeroCartao); } private static string getExtrato(string numeroCartao) { // 用StringBuilder累加所有交易记录,比直接字符串拼接更高效 var resultado = new StringBuilder(); using (var cn = new SqlConnection("Data Source=MAD-PC-023\\SQLEXPRESS;Database=bank;Trusted_Connection=True;")) { cn.Open(); // 参数化SQL语句,避免注入风险 var query = "SELECT CardNumber, Deposit, Withdraw, DataHora FROM MoveInfo WHERE CardNumber = @CardNumber"; using (var cmd = new SqlCommand(query, cn)) { // 添加参数并赋值 cmd.Parameters.AddWithValue("@CardNumber", numeroCartao); var reader = cmd.ExecuteReader(); // 遍历所有匹配的交易记录 while (reader.Read()) { var cartaoNumero = reader.GetString(0); var dataHora = reader.GetDateTime(3); if (reader.IsDBNull(1)) { // Deposit为空,判定为取款操作 var valorLevantamento = reader.GetDecimal(2); resultado.AppendLine($" O cartão nº {cartaoNumero} levantou: {valorLevantamento} às: {dataHora}"); } else { // Deposit不为空,判定为存款操作 var valorDeposito = reader.GetDecimal(1); resultado.AppendLine($" O cartão nº {cartaoNumero} depositou: {valorDeposito} euros às: {dataHora}"); } } } } // 无记录时返回提示,否则返回所有拼接好的交易内容 return resultado.Length == 0 ? "Nenhuma transação encontrada para este cartão." : resultado.ToString(); }
关键修改说明
- 替换字符串拼接为参数化查询:通过
@CardNumber参数传递卡号,彻底规避SQL注入风险 - 用StringBuilder收集所有记录:避免每次拼接字符串产生新对象,同时能完整保留所有交易记录
- 修正空值判断逻辑:使用
reader.IsDBNull(index)判断字段是否为数据库NULL,避免抛出异常 - 遍历所有匹配记录:移除循环内的
return语句,确保所有记录都被读取并拼接 - 改用数值类型读取金额:假设Deposit和Withdraw是数值类型(如Decimal),用
GetDecimal()读取比GetString()更合理,避免类型转换问题
内容的提问来源于stack exchange,提问作者user20571251
相关产品推荐
相关产品推荐

