You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么无法将MS-SQL数据库的所有表读取到DataSet中

报错含义

你遇到的报错是SQL Server ADO.NET提供程序的经典限制:默认状态下,同一个数据库连接同一时间只能有一个处于活动状态的DataReader。你当前外层通过ExecuteReader()打开了读取表名的SqlDataReader,在该Reader未关闭、仍在逐行读取的过程中,又用同一个连接让SqlDataAdapter发起了查询表数据的新请求,两个操作争夺同一个连接的使用权,就触发了该错误。
该报错和SqlDataAdapter无关,它本身没有Close()方法,Fill操作执行完成后会自动释放内部关联的命令资源,不需要手动关闭。

解决方案

方案1(优先推荐):先读取全量表名再拉取单表数据

先把所有表名读取到本地的List中存储,关闭占用连接的DataReader后,再循环遍历表名列表拉取每个表的内容,从根源上避免连接占用冲突。
修改后的代码示例:

try
{   
    DbConnection.Open();
    List<string> tableNames = new List<string>();
    
    // 第一步:先读取所有表名存到本地,读完立即关闭DataReader
    using (var sqlCommand = DbConnection.CreateCommand())
    {
        sqlCommand.CommandText = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES";
        using (var sqlDataReader = sqlCommand.ExecuteReader())
        {
            while (sqlDataReader.Read())
            {
                tableNames.Add(sqlDataReader.GetString(0));
            }
        }
    }

    // 第二步:循环拉取每个表的数据,此时无其他DataReader占用连接
    cmb_Table_Names.Items.Clear();
    dataSet.Tables.Clear();
    foreach (var tableName in tableNames)
    {
        cmb_Table_Names.Items.Add(tableName);
        DataTable dt_tmp = new DataTable();
        using (var da = new SqlDataAdapter($"SELECT * FROM {tableName}", DbConnection)) 
        {
            da.Fill(dt_tmp);
        }
        dataSet.Tables.Add(dt_tmp);
    }
}
catch (Exception ex)
{  
    MessageBox.Show(ex.Message, "Reading DB failed!!!", MessageBoxButton.OK);
}

上述代码额外增加了using语句包裹可释放资源,避免出现资源泄漏问题。

方案2:开启多活动结果集(MARS)

如果业务场景确实需要在同一个连接上同时执行多个查询,可以修改数据库连接字符串,添加配置项MultipleActiveResultSets=True,开启后即可支持同一连接上存在多个活动的查询操作。该方案不需要修改业务逻辑,但会小幅增加连接的资源占用,没有特殊需求时优先选择方案1。

内容的提问来源于stack exchange,提问作者Dominique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:21:03