C#-MySQL-ASP.NET:检测不存在的表时代码失效问题排查
问题分析与修复方案
你的代码核心问题是逻辑流程错误,当表不存在时,检测查询不会抛出异常,导致catch块完全没执行,最终走到了最后的默认返回。另外代码里还有几个SQL和操作上的错误,逐一拆解:
主要问题点
- 错误的异常依赖:你以为表不存在时会触发异常,但实际检测表的查询是查
information_schema.tables,即使目标表不存在,这个查询也会正常返回count=0,不会抛异常,所以catch块永远不会进入。 - 冗余且错误的数据库操作:在
count=0之后,你调用myCommand.ExecuteReader(),但之前已经用ExecuteScalar()获取了查询结果,重复执行会触发InvalidOperationException;而且这部分操作完全没必要,因为你不需要读取任何数据。 - 创建表的SQL语法错误:表名用了单引号
'book_details',MySQL中标识符(表名、列名)应该用反引号`包裹,单引号是用来包裹字符串的,会导致SQL执行失败。 - 不必要的手动关闭连接/阅读器:
using块会自动释放连接和命令资源,手动调用Close()属于冗余操作,甚至可能引发问题。 - 创建表后的无效操作:
CREATE TABLE是DDL语句,用ExecuteNonQuery()执行即可,之后调用ExecuteReader()会报错,因为DDL没有结果集。
修复后的代码
DataTable table = new DataTable(); string sqlDataSource = _configuration.GetConnectionString("EmployeeAppCon"); using (MySqlConnection mycon = new MySqlConnection(sqlDataSource)) { string tableName = "book_details"; // 用参数化查询避免SQL注入,同时修正标识符包裹方式 string checkQuery = @"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = @DatabaseName AND table_name = @TableName"; mycon.Open(); using (MySqlCommand checkCommand = new MySqlCommand(checkQuery, mycon)) { // 添加参数,避免SQL注入风险 checkCommand.Parameters.AddWithValue("@DatabaseName", mycon.Database); checkCommand.Parameters.AddWithValue("@TableName", tableName); int count = Convert.ToInt32(checkCommand.ExecuteScalar()); if (count > 0) { return new JsonResult("Table Exists"); } // 表不存在,直接执行创建表逻辑,不需要走catch string createQuery = $@"CREATE TABLE `{tableName}` ( ISBN int NOT NULL, BookName varchar(200), BookDescription varchar(1000), Price decimal(4,2), Author varchar(150), Genre varchar(100), Publisher varchar(150), YearPublished int, CopiesSold int, PRIMARY KEY (ISBN))"; using (MySqlCommand createCommand = new MySqlCommand(createQuery, mycon)) { createCommand.ExecuteNonQuery(); return new JsonResult("Table Doesn't Exist, it has been created."); } } // 只有当连接失败等极端情况才会走到这里 return new JsonResult("Connection was never established"); }
额外优化建议
- 参数化查询:原代码用字符串拼接的方式构建查询,存在SQL注入风险,修复后的代码使用了参数化查询,更安全。
- 数据类型修正:
int(255)在MySQL里没有意义,int的长度只是显示宽度,直接写int即可。 - 异常处理:如果需要捕获数据库连接或执行中的异常,可以在
mycon.Open()和整个操作外层添加try-catch,但不要依赖异常来控制业务逻辑。
内容的提问来源于stack exchange,提问作者Brandon Torrens
相关产品推荐
相关产品推荐

