";当读取器关闭时调用Read的尝试无效”;使用SqlDataReader时

本文关键字:无效 SqlDataReader 使用 Read 调用 读取 quot | 更新日期: 2023-09-27 18:21:08

1)我有以下代码:

private static sqlDataReader gCandidateList = null;
public SqlDataReader myCandidateList
{
    set
    {
        gCandidateList = value;
    }
    get
    {
        return gCandidateList;
    }
}

2) 在FormA中,我有:

sqlConn.ConnectionString = mySettings.myConnString;
sqlConn.Open();
SqlCommand cmdAvailableCandidate = new SqlCommand(tempString, sqlConn);
SqlDataReader drAvailableCandidate = cmdAvailableCandidate.ExecuteReader();
mySettings.myCandidateList = drAvailableCandidate;
sqlConn.Close();

3) 在FormB中,我想重复使用保存在myCandidatList中的数据,所以我使用:

SqlDataReader drCandidate = mySettings.myCandidateList;
drCandidate.Read();

4) 然后我得到了错误"当阅读器关闭时,调用Read的尝试无效。"

5) 我尝试了上面(3)中的mySettings.myCCandidateList.Read(),但再次收到相同的错误消息。

6) 如何重新打开SqlDataReader drCandidate以读取数据?

7) 非常感谢您的建议和帮助。

";当读取器关闭时调用Read的尝试无效”;使用SqlDataReader时

一旦连接为closeddisposed,就无法读取读取器。如果稍后要在代码中使用这些行(获取结果),则需要创建一个ListDataTable

例如,

System.Data.DataTable dt = new System.Data.DataTable();
dt.Load(drAvailableCandidate);

如果您想在稍后阶段使用数据读取器,您必须将其指定为ExecuteReader方法的参数。您在FormA中的代码应更改如下。

sqlConn.ConnectionString = mySettings.myConnString;  
sqlConn.Open();  
SqlCommand cmdAvailableCandidate = new SqlCommand(tempString, sqlConn);  
SqlDataReader drAvailableCandidate = cmdAvailableCandidate.ExecuteReader(CommandBehavior.CloseConnection);  
mySettings.myCandidateList = drAvailableCandidate;  
sqlConn.Close(); 

请确保在使用数据读取器后对其进行处理,因为在关闭数据读取器之前,与数据库的连接将保持打开状态。最好更改FormB中的代码,如下所示。

using (mySettings.myCandidateList)
{
mySettings.myCandidateList.Read();  
}

在尝试从读取器读取之前,您正在关闭连接。那行不通。

当您对SqlConnection对象(sqlConn.Close();)调用Close时,它会关闭连接和数据读取器。这就是为什么当您尝试从FormB读取SqlDataReader时会出现错误。

您需要做的是更改myCandidateList属性的定义,以返回从drAvailableCandidate读取器中提取的数据的表示形式。

从本质上讲,您需要做的是遍历drAvailableCandidate对象中的行,提取值并将其缓存在属性中以供以后检索。

只是为了增加已经给出的答案,如果您使用async/await,那么不等待SqlConnection的using块内的操作很容易陷入困境。例如,执行以下操作可以给出报告的错误

public Task GetData()
{
    using(new SqlConnection(connString))
    {
        return SomeAsyncOperation();
    }
}

这里的问题是,我们没有在using中等待操作,因此在实际执行underlines异步操作之前,它已经被处理掉了。很明显,但以前我也遇到过。

正确的做法是在使用中等待。

public async Task GetData()
{
    using(new SqlConnection(connString))
    {
        await SomeAsyncOperation();
    }
}