C# UWP中SQLite WHERE子句使用Input.Text传参与空值报错解决
问题根因
你当前的代码存在3个直接导致异常和隐患的问题:
- 字符串拼接SQL时引号转义逻辑错误:你手动拼接的条件最终生成的SQL中,画廊名称被错误包裹了转义双引号,而非SQL语法要求的单引号,导致WHERE条件无法匹配到任何画廊记录。
avg()聚合函数在无匹配行时会返回NULL,直接调用GetDouble(0)读取NULL值就触发了你看到的InvalidOperationException。 - 字符串拼接用户输入属于明确的反模式:存在SQL注入风险,且无法自动处理输入中包含单引号、特殊字符的场景,哪怕是本地应用也不推荐使用。
- 代码存在逻辑缺陷:读取结果前未做DBNull校验,数据库连接关闭的代码被截断(
dataManager.database.Clos),会引发后续连接泄漏问题。
修复方案(遵循C# SQLite最佳实践)
核心是改用参数化查询,完全放弃手动拼接用户输入到SQL字符串的写法,参数化会自动处理语法转义、特殊字符匹配,从根源避免注入和引号写错的问题。
1. 修正按钮点击事件逻辑
private void totalWorthBtn_Click(object sender, RoutedEventArgs e) { // SQL语句用@参数名做占位符,不拼接任何用户输入 const string querySql = @" SELECT round(avg(Artwork.worth),2) as avgArtworkWorth, Gallery.galleryName FROM Gallery INNER JOIN Artwork ON Gallery.GalleryID = Artwork.galleryiD WHERE Gallery.galleryName = @galleryName;"; // 传入参数执行查询,不需要给参数值加任何引号 dataManager.ArtworkAvgQuery(querySql, new Dictionary<string, object> { {"@galleryName", Input.Text.Trim()} }); double avgWorth = 0; string matchedGallery = string.Empty; while (dataManager.queryResult.Read()) { // 读取值前必须先判断是否为DBNull if (!dataManager.queryResult.IsDBNull(0)) { avgWorth = dataManager.queryResult.GetDouble(0); } if (!dataManager.queryResult.IsDBNull(1)) { matchedGallery = dataManager.queryResult.GetString(1); } if (firstPass) { counter++; } Debug.WriteLine($"查询结果:画廊{matchedGallery}的艺术品平均价值为{avgWorth}"); } firstPass = false; // 正确关闭结果集和数据库连接,不要写截断代码 dataManager.queryResult.Close(); dataManager.database.Close(); // 可选:无匹配结果时给用户提示 if (string.IsNullOrEmpty(matchedGallery)) { // 这里可以加弹窗提示"未找到对应画廊的记录" } }
2. 调整SQLManage类的查询方法支持参数传递
// 重构查询方法,支持接收参数集合 public void ArtworkAvgQuery(string sql, Dictionary<string, object> sqlParams = null) { // 以下是基于Microsoft.Data.Sqlite的通用实现,如果你用其他SQLite驱动逻辑一致 using (var cmd = new SQLiteCommand(sql, database)) { // 自动加载传入的参数,驱动会自动处理转义、类型匹配 if (sqlParams != null) { foreach (var param in sqlParams) { cmd.Parameters.AddWithValue(param.Key, param.Value); } } // 执行查询赋值给公共的queryResult字段 queryResult = cmd.ExecuteReader(); } }
验证说明
按照你的测试数据,输入CatLand时,会正确匹配到ID为4的画廊,关联2件艺术品计算出平均价值为45250,不会出现NULL异常。如果输入不存在的画廊名称,DBNull判断逻辑会拦截异常,你可以自定义无匹配时的交互提示。
内容的提问来源于stack exchange,提问作者Captured Night
相关产品推荐
相关产品推荐

