C#结合SQLite查询数据表列数据的实现及异常处理方法
问题说明
使用DB Browser创建Users.db数据库、手动建立Users表并添加字段后,通过C# SQLite类库查询指定邮箱对应的password字段时,抛出“不应使用TableMapping查询数据”的异常,原实现代码如下:
try { SQLiteConnection conn = new SQLiteConnection("users.db"); //获取用户在文本框中输入的邮箱地址 string email = textBox1.Text; //定义在数据表上执行的SQL命令文本 string query = "SELECT password FROM users WHERE email=" + email; //定义新的SQLiteCommand对象 SQLiteCommand command = new SQLiteCommand(conn); //设置command对象的查询命令文本 command.CommandText = query; //如何通过command.ExecuteQuery提取返回行中的数据? var data = command.ExecuteQuery<TableMapping>(); if (data != null) { //尝试获取返回行数据时,SQLite抛出异常,提示不应使用TableMapping查询数据 } }catch(SQLiteException exc){ Console.WriteLine(exc.Message); }
原代码问题点
- 资源未正确释放:
SQLiteConnection和SQLiteCommand都是非托管资源,没有用using语句包裹,执行完后会出现资源泄漏。 - SQL写法错误:直接拼接用户输入到SQL语句,既存在SQL注入风险,字符串类型的查询值也没有做转义、加引号处理,本身就存在语法错误;另外代码里写的连接字符串是
users.db,和实际创建的Users.db文件名大小写不一致,在区分大小写的文件系统下会直接连错库。 - 方法调用错误:
ExecuteQuery<T>要求传入和查询结果字段匹配的自定义实体类作为泛型参数,TableMapping是SQLite库内部的映射实现类,不能直接作为泛型参数传入使用。 - 方法选型错误:当前需求是查询匹配条件的单个
password字段值,不需要用全结果集映射的查询方法。
正确实现方式
针对当前只需要查询单个字段值的场景,用ExecuteScalar方法配合参数化查询即可,代码如下:
try { // using语句会在代码块执行结束后自动释放连接资源,无需手动调用Close using SQLiteConnection conn = new SQLiteConnection("Users.db"); string email = textBox1.Text.Trim(); // 用占位符写查询语句,不要拼接用户输入 string query = "SELECT password FROM users WHERE email = ?"; // 传入参数创建Command,自动完成参数绑定,避免注入和转义问题 using SQLiteCommand command = conn.CreateCommand(query, email); // ExecuteScalar返回查询结果第一行第一列的值,直接按目标类型转换即可 string password = command.ExecuteScalar<string>(); if (!string.IsNullOrEmpty(password)) { // 此处password就是匹配到的密码,可直接做后续校验逻辑 } else { // 未查询到对应邮箱的记录 } } catch (SQLiteException exc) { Console.WriteLine(exc.Message); }
如果后续需要查询多列数据、映射到结构化对象,不要使用TableMapping,自行定义和表字段匹配的实体类即可,示例:
// 自定义和表字段对应的实体类,属性名需要和表列名保持一致 public class User { public string Email { get; set; } public string Password { get; set; } } // 查询时泛型传入自定义的实体类 List<User> queryResult = conn.Query<User>("SELECT email,password FROM users WHERE email = ?", email);
注意:所有涉及用户输入的数据库查询,都要使用参数化传值的方式,禁止直接拼接SQL字符串,避免SQL注入风险,同时也不需要手动处理特殊字符转义、引号包裹的问题。
内容的提问来源于stack exchange,提问作者TechGeek
相关产品推荐
相关产品推荐

