我写的代码运行时,经常报错,有时是这个错误:
ExecuteReader 要求已打开且可用的连接。连接的当前状态为正在连接。偶尔会出现另外一个错误:
已有打开的与此命令相关联的 DataReader,必须首先将它关闭。刚刚又测试,偶尔又会出现一个错误:
阅读器关闭时尝试调用 Read 无效。而偶尔也会正常运行,不过次数很少而我只是使用Thread调用我的代码里的ExecuteDataTable方法
就一直报错
我的SqlHelper代码如下:
public virtual void ExecuteDataTable(ref DataTable refDt, string sql)
{
    if (refDt == null)
    {
        refDt = new DataTable("DataTable1");
    }
    using (DbCommand com = CreateCommand())
    {
        try
        {
            // 创建数据库连接,并指向Command
            DbConnection con = OpenConnection();
            com.Connection = con;
            com.CommandText = sql;            com.CommandType = CommandType.Text;            DbDataAdapter dap = CreateAdapter();
            dap.SelectCommand = com;            dap.Fill(refDt);
        }
        catch (Exception e)
        {
            throw e;
        }
        finally
        {
            CloseConnection(com.Connection);
        }
    }
}
protected override DbConnection OpenConnection()
{
    connection = new SqlConnection(ConnectionString);
    connection.Open();
    return connection;
}public override DbDataAdapter CreateAdapter()
{
    DbDataAdapter dap = new SqlDataAdapter();
    return dap;
}public override DbCommand CreateCommand()
{
    DbCommand ret = new SqlCommand();
    return ret;
}
protected virtual void CloseConnection(DbConnection con)
{
    if (con != null && con.State != ConnectionState.Closed)
    {
        con.Close();
        //con.Dispose();
        con = null;
    }
}

解决方案 »

  1.   

    调用的代码:
    for(int i=0;i<10;i++){
       new Thread(AddColumns).Start(tb);
    }private void AddColumns(string tb){
      DataTable a = null;
      string sql = "select * from " + tb;
      ExecuteDataTable(a, sql);
    }
      

  2.   

    上面的AddColumns,参数是object,其它删除了一些不相干的代码
      

  3.   

    测试发现,下面的10改成2,就很少报错,改成3,就频繁报错,汗……
    for(int i=0;i<10;i++){
      new Thread(AddColumns).Start(tb);
    }
    哪位多线程的大侠指导一下吧而且使用SqlServer2005的活动监视器发现,那些出错的线程中创建的连接,怎么都没有关闭,还在AWAITING_COMMAND中
      

  4.   

    SqlDataAdapter fill之前似乎不需要com.Open()的么
    我觉得这里面
    protected override DbConnection OpenConnection()
    { }
    protected virtual void CloseConnection(DbConnection con)
    { }
    这2个都没有作用么似乎.SqlDataAdapter adp = new SqlDataAdapter("selectCommand", "connString");
    DataSet ds = new DataSet();
    adp.Fill(ds);
    这样就好了么
      

  5.   

    找到错误原因了
    我在OpenConnection方法里,使用的是类成员变量:connection 然后在多线程里,多次使用同一个实例的这个成员变量来进行操作
    在执行的时候,这个成员变量就可能刚被打开,又被另一个线程调用了
    看来每次都要定义一个新的变量才行
      

  6.   

    不过很奇怪的是,我即使在代码里显式的关闭SqlConnection,在SqlServer2005的活动监视器中,依然会存在这个连接,只是处于空闲状态
      

  7.   

    多线程, 我感觉使用各自使用私有的 connection 效率会高一些连接关闭以后, 仍然存在, 是连接池为了提高性能 , 将连接缓存起来
      

  8.   

    使用Connection在之前没有关闭,又重复使用它
    Singleton模式只能有一个实例
    数据库连接用后要及时释放,以供其他的连接使用,
      

  9.   

    简单的加一个局部变量定义,就解决问题了,看来万事还要靠自己最好:
    protected override DbConnection OpenConnection()
    {
        DbConnection connection = new SqlConnection(ConnectionString);
        connection.Open();
        return connection;
    }散分散分
      

  10.   

    楼上,我做的SqlHelper是定义一个DbBase,然后从这个基类扩展出SqlServer、Oracle、Oledb、MySql等子类,所以用Override现在帖子加到300分了,大家踊跃参与,散分拉
      

  11.   

    我以前听说过,connection最好定义成private,否则回遇到很多奇怪的问题,大概说的就是这个吧,connection设置成public他们就胡乱用了…………
      

  12.   

    实际上我都有及时断开
    但是因为使用的是同一个实例的同一个成员变量
    导致a线程正在用这个成员操作的时候,b线程把这个成员的值修改了
    此时a线程去关闭连接的时候,关闭了b的连接,导致b出错了并不是没有及时关闭连接的原因。
      

  13.   

    这个成员也是private的,并不是public的
    因为在OpenConnection方法中修改了它的值,导致线程操作起了冲突。