我正在尝试将MS-SQL数据库的所有表读取到由一组DataTables组成的DataSet中。为此,我写了一段源代码:
try
{
DbConnection.Open();
sqlCommand = DbConnection.CreateCommand();
sqlCommand.CommandText = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES";
// INFORMATION_SCHEMA.TABLES contains the names of all the tables.
sqlDataReader = sqlCommand.ExecuteReader();
cmb_Table_Names.Items.Clear(); // combobox for keeping table names.
while (sqlDataReader.Read())
{
string tmp_Table_Name = sqlDataReader.GetString(0);
cmb_Table_Names.Items.Add(tmp_Table_Name);
DataTable dt_tmp = new DataTable();
using (var da = new SqlDataAdapter($"SELECT * FROM {tmp_Table_Name}",
DbConnection))
{
da.Fill(dt_tmp); // see "stackoverflow.com/questions/68919147"
}
dataSet.Tables.Add(dt_tmp);
}
sqlDataReader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Reading DB failed!!!", MessageBoxButton.OK);
}
我在da.Fill(dt_tmp);
线掉进了我的Exception
? ex
在即时窗口中的结果为:
{"There is already an open DataReader associated with this Command which must be closed first."}
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233079
HelpLink: null
InnerException: null
Message: "There is already an open DataReader associated with this Command which must be closed first."
Source: "System.Data"
StackTrace: " at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)rn
at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)rn
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)rn
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)rn
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)rn
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)rn
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)rn
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)rn
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)rn
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)rn
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)rn
at Database_Handling.MainWindow.Btn_Read_DB_Click(Object sender, RoutedEventArgs e) in <filename>
TargetSite: {Void ValidateConnectionForExecute(System.Data.SqlClient.SqlCommand)}
这意味着什么(尤其是因为我只有一个SqlDataReader
)
这是否意味着我需要关闭SqlAdapter
da
或其他什么?(我已经检查过:没有da.Close()
方法)
这是否意味着我不能在读取另一个SQL命令时启动另一个命令?(我想这将是一个主要的限制)
。。。
有人有主意吗
提前感谢
多亏了Olivier Rogier的文档URL,我终于找到了一个解决方案:
它提到Fill()
方法隐式使用DataReader
因此,我决定删除任何(Sql)DataReader
对象的嵌套,这将导致以下代码:
try
{
DbConnection.Open();
sqlCommand = DbConnection.CreateCommand();
sqlCommand.CommandText = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES";
sqlDataReader = sqlCommand.ExecuteReader();
cmb_Table_Names.Items.Clear();
while (sqlDataReader.Read())
{
cmb_Table_Names.Items.Add(sqlDataReader.GetString(0));
}
sqlDataReader.Close(); // <== close first DataReader
foreach (string tmp_Table in cmb_Table_Names.Items)
{
DataTable dt_tmp = new DataTable();
using (var da = new SqlDataAdapter($"SELECT * FROM [{tmp_Table}]",
DbConnection))
{
da.Fill(dt_tmp); // <== use the second implicit DataReader
}
dataSet.Tables.Add(dt_tmp);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Reading DB failed!!!", MessageBoxButton.OK);
}