另一个 "Invalid attempt to read when no data is present." 错误

Yet another "Invalid attempt to read when no data is present." error

我正在尝试从我的数据库中的视图中提取一个字段。我确定有这个实例的数据,我正确设置了 SQLDataReader(我相信),调试器验证我在 DataReader 中有行,但是当我尝试读取时出现错误。

代码如下:

    public string[] getReasons(string Accession) {
        string[] reasonList = new string[0];
        SqlParameter accNumber = new SqlParameter();
        accNumber.SqlDbType = System.Data.SqlDbType.VarChar;
        accNumber.ParameterName = "@Accession";
        accNumber.Value = Accession;
        string selectText = "select reason from pendingList where accession = @Accession";
        SqlCommand selectStmt = new SqlCommand(selectText,toPending);
        selectStmt.Parameters.Add(accNumber);

        if (selectStmt.Connection.State == System.Data.ConnectionState.Closed) {
            selectStmt.Connection.Open();
        }
        SqlDataReader pendList = selectStmt.ExecuteReader();

        while (pendList.Read()) {
            reasonList[reasonList.Length] = pendList["reason"].toString();
        }

        pendList.Close();

        return reasonList;
    }

我调用 getReasons('RAM4658980')。我已验证以下 SQL 查询

select reason 
from pendingList 
where accession = 'RAM4658980'

returns 正好一行。 pendList 变量如下所示:

我不确定为什么会收到 "Enumeration yielded no results";在 reasonList[reasonList.Length] = pendList["reason"].toString(); 这一步,我自然会得到 "Invalid attempt to read ..." 错误。我错过了什么?

你不应该使用调试器 "verify that you have rows in a reader"。虽然 SqlDataReader(和一般的 DbDataReader)实现了 IEnumerable,但它们很特殊,因为 reader 是向前只读数据库游标的托管等价物,因此在迭代时,它确实消耗 底层游标,或者简单地说,它可以只迭代一次。如果您使用调试器,您实际上是在发射一颗子弹。

改为验证缓冲结果(reasonList 在您的情况下)。

更新: 事实上,除了上述之外,您的代码中还有一个错误 - reasonList 数组。为了更正它,使用类似这样的东西(注意 new List<string>reasonList.AddreasonList.ToArray):

public string[] getReasons(string Accession) {
    var reasonList = new List<string>();
    SqlParameter accNumber = new SqlParameter();
    accNumber.SqlDbType = System.Data.SqlDbType.VarChar;
    accNumber.ParameterName = "@Accession";
    accNumber.Value = Accession;
    string selectText = "select reason from pendingList where accession = @Accession";
    SqlCommand selectStmt = new SqlCommand(selectText,toPending);
    selectStmt.Parameters.Add(accNumber);

    if (selectStmt.Connection.State == System.Data.ConnectionState.Closed) {
        selectStmt.Connection.Open();
    }
    SqlDataReader pendList = selectStmt.ExecuteReader();

    while (pendList.Read()) {
        reasonList.Add(pendList["reason"].toString());
    }

    pendList.Close();

    return reasonList.ToArray();
}