错误’已经有一个与此命令关联的打开的datareader,必须先关闭’
运行时错误’已经有一个与此命令关联的打开的datareader,必须先关闭’
objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn); objDataReader = objCommand.ExecuteReader(); while (objDataReader.Read()) { objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + objDataReader[0] + "')", objConn); objInsertCommand.ExecuteNonQuery();//Here is the error } objDataReader.Close();
我不能在这里定义任何存储过程。 任何帮助我们都会感激。
如何通过Fill将数据拉入DataSet,然后遍历它以通过NonQuery执行插入?
IDbDataAdapter da; IDbCommand selectCommand = connection.CreateCommand(); selectCommand.CommandType = CommandType.Text; selectCommand.CommandText = "SELECT field1, field2 FROM sourcetable"; connection.Open(); DataSet selectResults= new DataSet(); da.Fill(selectResults); // get dataset selectCommand.Dispose(); IDbCommand insertCommand; foreach(DataRow row in selectResults.Tables[0].Rows) { insertCommand = connection.CreateCommand(); insertCommand.CommandType = CommandType.Text; insertCommand.CommandText = "INSERT INTO tablename (field1, field2) VALUES (3, '" + row["columnName"].ToString() + "'"; } insertCommand.Dispose(); connection.Close();
不需要做所有这些,只需打开MARS,您的问题就会得到解决。 在你的连接字符串中只需添加MultipleActiveResultSets=True;
当它仍然在读取数据读取器的内容时,您无法对该连接执行操作 – 该错误非常具有描述性。
您的替代方案是:
1)首先使用DataSet检索所有数据,或者使用阅读器填充其他一些集合,然后在初始选择完成后立即运行所有数据。
2)为insert语句使用不同的连接。
您最好的选择是将所需信息读入列表,然后迭代列表以执行插入,如下所示:
List values = new List (); using(SqlCommand objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn)) { using(SqlDataReader objDataReader = objCommand.ExecuteReader()) { while(objDataReader.Read()) { values.Add(objDataReader[0].ToString()); } } } foreach(String value in values) { using(SqlCommand objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + value + "')", objConn)) { objInsertCommand.ExecuteNonQuery(); } }
INSERT INTO tablename (field1, field2) SELECT 3, field1 FROM sourcetable
单个SQL语句,而不是每个插入一个。 不确定这是否适用于您的实际问题,但对于您提供的示例,这比一次执行一个查询要好得多。
另外,请确保您的代码使用参数化查询,而不是在SQL语句中按原样接受字符串 – 您的示例对SQL注入开放。
提出了一些有效的建议,以及改进实施的建议。 由于现有代码没有清理读卡器,我达到了MARS限制,所以我想把一个更可敬的样本放在一起:
const string connectionString = @"server=.\sqlexpress;database=adventureworkslt;integrated security=true"; const bool useMARS = false; using (var objConn = new System.Data.SqlClient.SqlConnection(connectionString + (useMARS ? ";MultipleActiveResultSets=True" : String.Empty))) using (var objInsertConn = useMARS ? null : new System.Data.SqlClient.SqlConnection(connectionString)) { objConn.Open(); if (objInsertConn != null) { objInsertConn.Open(); } using (var testCmd = new System.Data.SqlClient.SqlCommand()) { testCmd.Connection = objConn; testCmd.CommandText = @"if not exists(select 1 from information_schema.tables where table_name = 'sourcetable') begin create table sourcetable (field1 int, field2 varchar(5)) insert into sourcetable values (1, 'one') create table tablename (field1 int, field2 varchar(5)) end"; testCmd.ExecuteNonQuery(); } using (var objCommand = new System.Data.SqlClient.SqlCommand("SELECT field1, field2 FROM sourcetable", objConn)) using (var objDataReader = objCommand.ExecuteReader()) using (var objInsertCommand = new System.Data.SqlClient.SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, @field2)", objInsertConn ?? objConn)) { objInsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("field2", String.Empty)); while (objDataReader.Read()) { objInsertCommand.Parameters[0].Value = objDataReader[0]; objInsertCommand.ExecuteNonQuery(); } } }
您使用的是哪个版本的SQL Server? 问题可能在于此:
(来自http://msdn.microsoft.com/en-us/library/9kcbe65k.aspx )
在SQL Server 2005之前使用SQL Server版本时,在使用SqlDataReader时,关联的SqlConnection正忙于为SqlDataReader提供服务。 在此状态下,除了关闭它之外,不能对SqlConnection执行任何其他操作。 在调用SqlDataReader的Close方法之前就是这种情况。
因此,如果这是导致问题的原因,则应首先读取所有数据,然后关闭SqlDataReader,然后才执行插入。
就像是:
objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn); objDataReader = objCommand.ExecuteReader(); List
将此添加到连接字符串应该可以解决问题。
MultipleActiveResultSets=true
选项1:必须在运行另一个查询之前执行查询和加载数据。
选项2:将MultipleActiveResultSets=true
添加到连接字符串的提供者部分。 请参阅以下示例:
尝试这样的事情:
//Add a second connection based on the first one SqlConnection objConn2= new SqlConnection(objConn.connectionString)) SqlCommand objInsertCommand= new SqlCommand(); objInsertCommand.CommandType = CommandType.Text; objInsertCommand.Connection = objConn2; while (objDataReader.Read()) { objInsertCommand.CommandText = "INSERT INTO tablename (field1, field2) VALUES (3, '" + objDataReader[0] + "')"; objInsertCommand.ExecuteNonQuery(); }
最佳解决方案:“CommandText”值只有问题。 让它成为SP或普通的Sql Query。
-
检查1:您在Sql Query中传递的参数值没有变化,并且在ExecuteReader中反复出现。
-
检查2:错误地形成了Sql Query字符串。
-
检查3:请按如下方式创建最简单的代码。
string ID = "C8CA7EE2"; string myQuery = "select * from ContactBase where contactid=" + "'" + ID + "'"; string connectionString = ConfigurationManager.ConnectionStrings["CRM_SQL_CONN_UAT"].ToString(); SqlConnection con = new SqlConnection(connectionString); con.Open(); SqlCommand cmd = new SqlCommand(myQuery, con); DataTable dt = new DataTable(); dt.Load(cmd.ExecuteReader()); con.Close();
为了便于处理,我使用以下编码模板:
`using (SqlConnection connection = new SqlConnection("your connection string")) { connection.Open(); using (SqlCommand cmd = connection.CreateCommand()) { cmd.CommandText = "Select * from SomeTable"; using (SqlDataReader reader = cmd.ExecuteReader()) { if(reader.HasRows) { while(reader.Read()){ // assuming that we've a 1-column(Id) table int id = int.Parse(reader[0].ToString()); } } } } connection.Close() }`