已经有一个与此命令关联的打开DataReader,必须先关闭它

时间:2012-01-26 18:38:39

标签: c# datareader

这是我的代码。

/// <summary>
/// Method calls stored procedure and fills DataSet of contacts associated with Lead
/// </summary>
/// <param name="leadID">The ID associated with a Lead</param>
/// <returns>contacts list as DataSet</returns>
public static DataSet GetContactResultSetByLead(int leadID)
{
    SqlCommand Sqlmd = new SqlCommand("dbo.proc_contact");
    Sqlmd.CommandType = CommandType.StoredProcedure;
    Sqlmd.Parameters.Add("@LeadInfoID", SqlDbType.Int).Value = leadID;

    Sqlmd.Connection = m_ConStr;
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd);

    DataSet data = new DataSet();
    try
    {
        da.Fill(data);
    }

    finally
    {
        m_ConStr.Close();
    }

    return data;
}

4 个答案:

答案 0 :(得分:9)

你的问题是你显然有一个m_ConStr的实例;如果同时调用该方法,则只有其中一个能够使用该连接,而另一个将因您收到的异常而失败。

请改用此模式:

using (SqlConnection conn  = new SqlConnection())
{
    conn.Open();
    Sqlmd.Connection = conn;
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd);
   //...etc
}

换句话说,不要将连接定义为类的全局变量。

答案 1 :(得分:5)

我建议你可以使用block来确保正确处理sqlconnection。

using (SqlConnection conn  = new SqlConnection())
{
    conn.Open();
    Sqlmd.Connection = conn;
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd);
    Dataset ds = new Datasest
    da.Fill(ds)
}

另一种方法是,如果需要,您还可以在连接中设置MARS属性。

SqlConnection m_ConStr;= new SqlConnection("Server= serverName;Database=yourDatabase;
        MultipleActiveResultSets=true;");

答案 2 :(得分:5)

所有短暂的IDisposable对象都没有“使用”。那么,通过扩展,您可能已经完成了类似的事情:

var reader = anotherCommand.ExecuteReader();
...

但这并没有处理/关闭读者。如果是这种情况,请添加“使用”:

using(var reader = anotherCommand.ExecuteReader()) {
    ...
}

无论我们如何退出,读者都会关闭。命令,连接,读者和交易都是一次性的,通常都应该使用“使用”。

答案 3 :(得分:1)

您正在尝试运行多个actice结果集(又名MARS)。

我想到了两种可能的解决方案:

  1. 在GetContractResultSetByLead
  2. 中打开一个新连接
  3. 在数据库服务器上启用MARS(如上面的链接所述)。