重构插入存储过程:优化C#控制台程序并解决输入跳过问题
解决Skills输入跳过问题并优化C#数据库插入代码
作为刚接触C#两天的开发者,你的代码已经完成了核心功能,很棒!下面我会先帮你解决输入被跳过的问题,再一步步讲解代码优化的方向和原因。
一、解决Skills输入被跳过的问题
问题根源
你用Console.Read()获取statusId时踩了一个常见的坑:
Console.Read()只会读取输入的第一个字符的ASCII值(比如输入"1"会返回49,而不是整数1)- 你输入完成后按下的回车键会留在输入缓冲区里
- 后续的
Console.ReadLine()会直接读取这个空回车,导致skillsInput被自动赋值为空,看起来像是输入被跳过了
修复代码
把获取statusId的逻辑改成用Console.ReadLine(),同时添加输入验证,避免用户输入非数字内容导致程序崩溃:
Console.WriteLine("Please Enter a 1 digit Status Id"); int statusId; // 循环直到用户输入有效的1位数字 while (!int.TryParse(Console.ReadLine(), out statusId) || statusId < 0 || statusId > 9) { Console.WriteLine("Invalid input! Please enter a 1-digit integer (0-9):"); } StatusId.Value = statusId;
二、代码效率与可读性优化建议
下面是几个符合C#最佳实践的优化点,每个点都会说明为什么要这么做:
1. 用using包裹SqlCommand
SqlCommand实现了IDisposable接口,需要手动释放资源。用using包裹可以确保命令对象在使用后自动销毁,避免资源泄漏:
using (SqlCommand testCMD = new SqlCommand("People_Insert", PubsConn)) { // 命令的配置和执行逻辑都放在这里 }
2. 简化参数添加逻辑
你可以合并参数的声明和配置,减少冗余代码,同时保持类型明确(尽量不用AddWithValue,它可能导致隐式类型转换错误):
// 输出参数 testCMD.Parameters.Add("@Id", SqlDbType.Int, 5).Direction = ParameterDirection.Output; // 输入参数可以链式配置,更简洁 testCMD.Parameters.Add("@Title", SqlDbType.NVarChar, 100).Value = titleInput; testCMD.Parameters.Add("@Bio", SqlDbType.NVarChar, 100).Value = bioInput;
3. 提取输入获取的辅助方法
重复的Console.WriteLine()和Console.ReadLine()可以封装成一个方法,减少代码重复,提升可读性:
private static string GetUserInput(string prompt) { Console.WriteLine(prompt); return Console.ReadLine()?.Trim() ?? string.Empty; // 处理null输入,去除首尾空格 }
使用示例:
string titleInput = GetUserInput("Please Enter a Title"); string bioInput = GetUserInput("Please Enter a Bio");
4. 添加异常处理
数据库操作可能遇到各种错误(比如连接失败、存储过程执行错误),添加try-catch块可以让程序更健壮,给用户友好的错误提示:
try { PubsConn.Open(); int rowsAffected = testCMD.ExecuteNonQuery(); Console.WriteLine($"Number of Rows: {rowsAffected}"); Console.WriteLine($"Return Value: {Id.Value}"); } catch (SqlException ex) { Console.WriteLine($"Database error occurred: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); }
5. 使用var简化变量声明
对于类型明确的变量,可以用var代替具体类型,让代码更简洁:
var titleInput = GetUserInput("Please Enter a Title"); var bioInput = GetUserInput("Please Enter a Bio");
三、优化后的完整代码
using System; using System.Data; using System.Data.SqlClient; namespace TestConsoleApp { class Program { static void Main(string[] args) { // 把连接字符串提取为常量,方便后续修改 const string connectionString = "Server=.\\SQLEXPRESS;Database=PeopleDatabase;Trusted_Connection=True;"; using (SqlConnection pubsConn = new SqlConnection(connectionString)) using (SqlCommand testCmd = new SqlCommand("People_Insert", pubsConn)) { testCmd.CommandType = CommandType.StoredProcedure; // 配置输出参数 var idParam = testCmd.Parameters.Add("@Id", SqlDbType.Int, 5); idParam.Direction = ParameterDirection.Output; // 获取用户输入 var titleInput = GetUserInput("Please Enter a Title"); var bioInput = GetUserInput("Please Enter a Bio"); var summaryInput = GetUserInput("Please Enter a Summary"); var headlineInput = GetUserInput("Please Enter a Headline"); var slugInput = GetUserInput("Please Enter a Unique Slug"); // 获取并验证StatusId Console.WriteLine("Please Enter a 1 digit Status Id"); int statusId; while (!int.TryParse(Console.ReadLine(), out statusId) || statusId < 0 || statusId > 9) { Console.WriteLine("Invalid input! Please enter a 1-digit integer (0-9):"); } var skillsInput = GetUserInput("Please Enter Skills"); var imageInput = GetUserInput("Enter an Image Url"); // 给输入参数赋值 testCmd.Parameters.Add("@Title", SqlDbType.NVarChar, 100).Value = titleInput; testCmd.Parameters.Add("@Bio", SqlDbType.NVarChar, 100).Value = bioInput; testCmd.Parameters.Add("@Summary", SqlDbType.NVarChar, 100).Value = summaryInput; testCmd.Parameters.Add("@Headline", SqlDbType.NVarChar, 100).Value = headlineInput; testCmd.Parameters.Add("@Slug", SqlDbType.NVarChar, 100).Value = slugInput; testCmd.Parameters.Add("@StatusId", SqlDbType.Int, 3).Value = statusId; testCmd.Parameters.Add("@Skills", SqlDbType.NVarChar, 100).Value = skillsInput; testCmd.Parameters.Add("@PrimaryImage", SqlDbType.NVarChar, 100).Value = imageInput; try { pubsConn.Open(); int rowsAffected = testCmd.ExecuteNonQuery(); Console.WriteLine($"Number of Rows: {rowsAffected}"); Console.WriteLine($"Return Value: {idParam.Value}"); } catch (SqlException ex) { Console.WriteLine($"Database error: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } /// <summary> /// 辅助方法:获取用户输入并处理空值 /// </summary> private static string GetUserInput(string prompt) { Console.WriteLine(prompt); return Console.ReadLine()?.Trim() ?? string.Empty; } } }
最后说明
- 修复后的代码彻底解决了Skills输入被跳过的问题
- 优化后的代码更简洁、更健壮,同时遵循了C#的资源管理和编码规范
- 注释部分可以帮助你快速理解每段代码的作用
内容的提问来源于stack exchange,提问作者Michael Chang
相关产品推荐
相关产品推荐

