SqlDataReader HasRows = True但没有数据

时间:2016-04-15 08:41:27

标签: c# sql-server sqlclient

我正在连接到SQL Server 2012数据库,以根据ID查询单个值。 (值得一提的是,这个数据库位于我的开发机器的另一个大陆的服务器上,所以延迟非常高。大约100ms左右。)

查询似乎成功执行。 HasRows对象的SqlDataReader属性设置为true,因此我尝试使用该值来分配变量。当我正常运行程序时,遇到消息'Given key was not present in the dictionary'的异常。如果我停止执行并检查SqlDataReader对象,并枚举结果。首先我被告知'enumeration yielded no results'然后当我继续执行时,我得到一个不同的例外,消息'invalid attempt to read when no data is present'

以下是相关代码:

SqlConnection sql_conn = new SqlConnection(ConnectionString);
SqlCommand sql_cmd = new SqlCommand(String.Format("select ItemType from ItemTable where ItemID='{0}'", item_id), sql_conn);

Console.WriteLine(sql_cmd.CommandText);

sql_conn.Open();

SqlDataReader rdr = sql_cmd.ExecuteReader();

rdr.Read();

if (rdr.HasRows) //True
{
    item_type= TypesMap[rdr["ItemType"].ToString()]; //Either 'given key not found in dictionary' or 'invalid attempt to read when no data is present'
}

我已在SQL Server Management Studio中执行了SQL语句,但它已成功完成。我尝试将ItemID硬编码到C#代码中的语句中,并且存在相同的错误。

我还可以做些什么来调试这个?在我尝试访问查询结果之前,一切似乎都没问题。

3 个答案:

答案 0 :(得分:3)

您必须调试:似乎TypesMap 没有从数据库中读取的密钥:

// Wrap IDisposable into using
using (SqlConnection sql_conn = new SqlConnection(ConnectionString)) {
  // Make SQL readable
  // Make SQL parametrized (and not formatted) when it's possible
  String sql = 
    @"select ItemType 
        from ItemTable 
       where ItemID = @prm_ItemId"; 

  // Wrap IDisposable into using
  using (SqlCommand sql_cmd = new SqlCommand(sql, sql_conn)) {
    // I don't know ItemID's type that's why I've put AddWithValue 
    sql_cmd.Parameters.AddWithValue("@prm_ItemId", item_id);

    // Wrap IDisposable into using
    using (SqlDataReader rdr = sql_cmd.ExecuteReader()) {
      // rdr.HasRows is redundant - rdr.Read() returns true if record has been read
      if (rdr.Read()) {
        String key = Convert.ToString(rdr.GetValue(0));
        // Put break point here: what is the "key" value?
        item_type = TypesMap[key];
      }
    }
  } 
}

编辑:正如Luke在评论中提到的,错误的原因是密钥比较应该是不区分大小写的,所以修正是要解释的。网如何比较键:

var TypesMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

...
TypesMap.Add("aBc", "xyz"); 
String test = TypesMap["Abc"]; // return "xyz"; notice "aBc" and "Abc"

答案 1 :(得分:2)

正如德米特里指出的那样,没有找到钥匙......&#39;不是数据库的东西,而是字典的东西。 下面我添加了一个简单的检查,以确保密钥在字典中 - 如果是,那么我们可以分配到item_type。

此外,如果HasRows()没有按照您的意愿行事,请尝试以下操作。这是我从DB读取的标准方式:

using (SqlDataReader results = sql_cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
    while (results.Read())
    {
        string Key = rdr["ItemType"].ToString();
        if (TypesMap.ContainsKey(Key))
            item_type = TypesMap[Key];       
    }
}

答案 2 :(得分:1)

我转换了:

dto.Id = (int)record["Id"];  

要:

dto.Id = (int)record[0]; 

这对我有用。