运行时错误'已经有一个与此命令关联的打开的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();
我无法在此定义任何存储过程。 任何帮助我们都会感激。
答案 0 :(得分:80)
无需完成所有操作,只需启用MARS即可解决问题。在您的连接字符串中,只需添加MultipleActiveResultSets=True;
答案 1 :(得分:7)
当它仍在处理读取数据读取器的内容时,您无法对该连接执行操作 - 该错误非常具有描述性。
您的替代方案是:
1)首先使用DataSet检索所有数据,或者使用阅读器填充其他一些集合,然后在初始选择完成后立即运行所有数据。
2)为插入语句使用不同的连接。
答案 2 :(得分:6)
如何通过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();
答案 3 :(得分:4)
您最好的选择是将所需信息读入列表,然后迭代列表以执行插入操作:
List<String> values = new List<String>();
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();
}
}
答案 4 :(得分:3)
INSERT INTO tablename (field1, field2)
SELECT 3, field1 FROM sourcetable
单个SQL语句,而不是每个插入一个。不确定这是否适用于您的实际问题,但对于您提供的示例,这比一次执行一个查询要好得多。
另外,请确保您的代码使用参数化查询,而不是在SQL语句中按原样接受字符串 - 您的示例对SQL注入是开放的。
答案 5 :(得分:2)
已经提出了一些有效的建议,以及改进实施的建议。由于现有代码没有清理读卡器,我达到了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();
}
}
}
答案 6 :(得分:1)
您使用的是哪个版本的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<object> values = new List<object>();
while (objDataReader.Read())
{
values.Add(objDataReader[0]);
}
objDataReader.Close();
foreach (object value in values)
{
objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + value + "')", objConn);
objInsertCommand.ExecuteNonQuery();
}
答案 7 :(得分:1)
将此添加到连接字符串应该可以解决问题。
MultipleActiveResultSets=true
答案 8 :(得分:1)
选项1: 必须在运行另一个查询之前执行查询和加载数据。
选项2:
将MultipleActiveResultSets=true
添加到连接字符串的提供者部分。请参阅以下示例:
<add name="DbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
答案 9 :(得分:0)
尝试这样的事情:
//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();
}
答案 10 :(得分:0)
最佳解决方案: 您的&#34; CommandText&#34;只会出现问题。值。让它成为SP或普通的Sql Query。
检查1:您在Sql Query中传递的参数值 在ExecuteReader中不会一次又一次地改变它。
检查2:错误地形成了Sql查询字符串。
检查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();
答案 11 :(得分:0)
为了便于处理,我使用以下编码模板:
`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()
}`