2010-10-01 43 views
24
error

tiempo de ejecución 'ya hay un DataReader abierto asociado con este comando que debe estar cerrada primer'error 'ya hay un DataReader abierto asociado con este comando que debe estar cerrada primer'

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(); 

No puedo definir cualquier procedimiento almacenado aquí. Cualquier ayuda sería apreciada.

+0

Consulte http://stackoverflow.com/questions/18475195/there-is-already-an-open-datareader-associated-with-this-command-which-must-be- c/20535263 # 20535263 – Lijo

Respuesta

6

¿Qué hay de tirar de los datos en un conjunto de datos a través de llenar y luego repetir a través de eso para realizar su inserción a través de 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(); 
+0

¿podría proporcionarme la sintaxis o el ejemplo? – Pradeep

+0

@Pradeep, ver arriba; He agregado un código de muestra. – Brad

0

intentar algo como esto:

//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(); 
} 
+0

Esto no funcionará, es lo mismo que lo que el OP ya está haciendo. –

+0

cierto, editado mi respuesta –

1

¿Qué versión de SQL Server está utilizando? El problema podría ser con esto:

(de http://msdn.microsoft.com/en-us/library/9kcbe65k.aspx)

Al utilizar versiones de SQL Server antes de SQL Server 2005, mientras se está utilizando el SqlDataReader, el SqlConnection asociado está ocupado sirviendo a la SqlDataReader. Mientras está en este estado, no se pueden realizar otras operaciones en la conexión Sql además de cerrarla. Este es el caso hasta que se llama al método Cerrar del SqlDataReader.

Por lo tanto, si esto es lo que está causando su problema, primero debe leer todos los datos, luego cierre el SqlDataReader y solo después de eso ejecute sus inserciones.

Algo así como:

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

No se puede realizar una acción en ese sentido, mientras que todavía está trabajando en leer el contenido de un lector de datos - el error es bastante descriptivo.

Sus alternativas son:

1) Recuperación de todos sus datos en primer lugar, ya sea con un conjunto de datos o utilizar el lector para poblar alguna otra colección, a continuación, ejecutar todos a la vez después de la inicial de selección se lleva a cabo.

2) Use una conexión diferente para sus instrucciones de inserción.

4

Lo mejor sería leer la información que necesita en una lista y luego la iteración de la misma para realizar sus insertos de este modo:

 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(); 
      } 
     } 
+0

1 para la única respuesta hasta el momento eso es la eliminación segura de los comandos y el lector – PHeiberg

3
INSERT INTO tablename (field1, field2) 
    SELECT 3, field1 FROM sourcetable 

una única sentencia SQL en lugar de uno por inserción. No estoy seguro si esto funcionará para su problema de la vida real, pero para el ejemplo que proporcionó, esta es una consulta mucho mejor que hacerlas de a una por vez.

En una nota lateral, asegúrese de que su código utiliza consultas con parámetros en lugar de aceptar cadenas como está dentro de la instrucción SQL - la muestra está abierta a la inyección de SQL.

80

No hace falta hacer todo eso, solo active MARS y su problema se resolverá.En la cadena de conexión sólo tiene que añadir se han dado MultipleActiveResultSets=True;

+1

verificado esto con SQL 2008. http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/78d3989a-8975-4930-998d-1eb907966f57 – user423430

+1

Funciona para mí. SQL Server 2008. – finitenessofinfinity

+0

Funciona para mí. SQL Server 2008. – Swag

2

varias sugerencias que funcionan muy bien, junto con recomendaciones para mejorar la aplicación. Me golpeó el límite de MARS debido al código existente no limpiar un lector, así que quería armar una muestra más respetable:

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(); 
    } 
} 
} 
1

La adición de esta cadena de conexión a debería solucionar el problema.

MultipleActiveResultSets=true 
0

Mejor Solución: Sólo hay un problema con su valor "CommandText". Que sea SP o consulta SQL normal.

  • Comprobación 1: El valor del parámetro que está pasando en su consulta SQL no está cambiando y pasando misma una y otra vez en su ExecuteReader.

  • Comprobación 2: cadena de consulta SQL se forma errónea.

  • Comprobación 3: Cree el código más simple de la siguiente manera.

    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(); 
    
0

el fin de que al ser dispuesto fácilmente utilizo el siguiente codificación-plantilla:

`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() 
     }` 
+0

Código que no funciona –

+0

¿Ha abierto la conexión antes de ejecutar el lector? ¿Estás seguro de que estás leyendo datos correctamente? –

+0

sí, pero todavía no hay resultados –

1

Opción 1: debe ejecutar datos de consulta y de carga antes de ejecutar otra consulta.

Opción 2: Añadir MultipleActiveResultSets=true a la parte del proveedor de la cadena de conexión. Véase el siguiente ejemplo:

<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" /> 
Cuestiones relacionadas