ADO.NET查询无返回结果:存在匹配数据却无输出问题排查
问题原因
你遇到的问题核心在于错误地将多个ID拼接成单个字符串参数传递给IN子句。从SQL Profiler捕获的语句能看到,@list被当作一个完整的字符串值'50','23','100'传入,SQL Server会把这个整体当成单一匹配项和Id字段对比——而你的Employees表里显然没有等于这个完整字符串的Id,所以不会返回任何结果。
解决方法
下面提供几种安全且有效的解决方式:
方法1:使用表值参数(推荐,避免SQL注入)
这是SQL Server 2008及以上版本的规范做法:
- 先在SQL Server中创建用户定义表类型:
CREATE TYPE dbo.IdList AS TABLE (Id VARCHAR(50))
- 修改C#代码,将列表数据传入表值参数:
public List<string> GetRecords(List<string> itemList) { itemList.Add("100"); List<string> employeeList = new List<string>(); using (var tvp = new DataTable()) { tvp.Columns.Add("Id", typeof(string)); foreach (var id in itemList) { tvp.Rows.Add(id); } string query = @"SELECT Id FROM Employees WHERE Id IN (SELECT Id FROM @list)"; using (SqlCommand sqlCommand = new SqlCommand(query, connection)) { sqlCommand.Parameters.Add(new SqlParameter("@list", SqlDbType.Structured) { TypeName = "dbo.IdList", Value = tvp }); using (var sqlDataReader = sqlCommand.ExecuteReader()) { while (sqlDataReader.Read()) { employeeList.Add(Convert.ToString(database.Sanitise(sqlDataReader, "Id"))); } } } } return employeeList; }
方法2:逐个添加参数(适合小批量ID)
如果不想创建表类型,可以为每个ID单独添加参数:
public List<string> GetRecords(List<string> itemList) { itemList.Add("100"); List<string> employeeList = new List<string>(); List<SqlParameter> parameters = new List<SqlParameter>(); string placeholders = string.Join(", ", itemList.Select((_, index) => $"@id{index}")); string query = $"SELECT Id FROM Employees WHERE Id IN ({placeholders})"; using (SqlCommand sqlCommand = new SqlCommand(query, connection)) { for (int i = 0; i < itemList.Count; i++) { var param = new SqlParameter($"@id{i}", SqlDbType.VarChar); param.Value = itemList[i]; sqlCommand.Parameters.Add(param); } using (var sqlDataReader = sqlCommand.ExecuteReader()) { while (sqlDataReader.Read()) { employeeList.Add(Convert.ToString(database.Sanitise(sqlDataReader, "Id"))); } } } return employeeList; }
方法3:使用STRING_SPLIT(SQL Server 2016+)
如果你的SQL Server版本支持STRING_SPLIT函数,可以将ID列表作为无引号字符串传入后拆分:
public List<string> GetRecords(List<string> itemList) { itemList.Add("100"); List<string> employeeList = new List<string>(); string idList = string.Join(",", itemList); string query = @"SELECT Id FROM Employees WHERE Id IN (SELECT value FROM STRING_SPLIT(@list, ','))"; using (SqlCommand sqlCommand = new SqlCommand(query, connection)) { sqlCommand.Parameters.AddWithValue("@list", idList); using (var sqlDataReader = sqlCommand.ExecuteReader()) { while (sqlDataReader.Read()) { employeeList.Add(Convert.ToString(database.Sanitise(sqlDataReader, "Id"))); } } } return employeeList; }
注意:若Id是数值类型,需在拆分后转换类型,比如SELECT CAST(value AS INT) FROM STRING_SPLIT(...)。
额外注意事项
- 确保
connection对象在使用前已调用connection.Open()打开 - 确保
employeeList在方法内正确初始化,避免空引用 - 始终避免直接拼接SQL字符串,防止SQL注入风险
内容的提问来源于stack exchange,提问作者Mishayl stabin
相关产品推荐
相关产品推荐

