SQLite QueryAsync查询指定用户MapPin时未执行无返回问题
SQLite查询指定用户点位无返回、QueryAsync执行中断问题
问题复现
初始版本方法可正常返回全部地图点位,功能运行正常,代码如下:
public async Task<ObservableCollection<MapPinModel>> GetPins(string userId) { var pins = await _database.Table<MapPinModel>().ToListAsync(); ObservableCollection<MapPinModel> retPins = new ObservableCollection<MapPinModel>(pins); return retPins; }
需求为筛选返回属于指定用户的点位,修改为手写SQL查询版本后出现异常:无任何返回结果,在声明pins变量的代码行添加断点可正常命中,但代码不会继续执行到后续ObservableCollection实例化转换逻辑,会直接中断,随后应用继续加载,QueryAsync方法始终未正常执行完成。修改后的异常代码如下:
public async Task<ObservableCollection<MapPinModel>> GetPins(string userId) { var pins = await _database.QueryAsync<MapPinModel>("SELECT Id, UserId, Name, Latitude, Longitude FROM MapPinModel WHERE UserId = '", userId + "'"); ObservableCollection<MapPinModel> retPins = new ObservableCollection<MapPinModel>(pins); return retPins; }
错误原因
- 手写SQL语法错误:传入的SQL字符串以
UserId = '结尾,没有闭合单引号,属于非法SQL语句,执行时会直接抛出语法错误 - 参数绑定用法错误:sqlite-net的
QueryAsync方法要求使用?作为参数占位符,按顺序传入参数值即可,不需要手动拼接单引号。原代码没有写占位符,反而把参数值拼接上单引号作为第二个参数传入,ORM无法完成参数绑定,同时手动拼接参数还存在SQL注入风险 - 异常被吞:异步方法抛出的SQL语法错误如果没有被当前调用栈捕获,会被全局未处理异常逻辑处理,不会在断点处停留,表现为代码直接中断跳回应用加载流程。
修复方案
方案1:使用LINQ查询(推荐,无需手写SQL,避免语法错误)
直接在Table方法后追加Where条件即可,ORM会自动生成参数化SQL,不会出现语法问题:
public async Task<ObservableCollection<MapPinModel>> GetPins(string userId) { var pins = await _database.Table<MapPinModel>() .Where(p => p.UserId == userId) .ToListAsync(); return new ObservableCollection<MapPinModel>(pins); }
方案2:修正手写SQL的参数绑定写法
如果需要手写自定义SQL,严格按照参数化查询规则编写,不要手动拼接参数值:
public async Task<ObservableCollection<MapPinModel>> GetPins(string userId) { // SQL中使用?作为参数占位符,不需要给字符串类型参数加单引号,直接传入原值即可 var pins = await _database.QueryAsync<MapPinModel>( "SELECT Id, UserId, Name, Latitude, Longitude FROM MapPinModel WHERE UserId = ?", userId); return new ObservableCollection<MapPinModel>(pins); }
内容的提问来源于stack exchange,提问作者dynmatt
相关产品推荐
相关产品推荐

