2010-10-01 2 views
24
ошибки

выполнения «уже существует открытое 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(); 

Я не могу определить любая хранимая процедура здесь. Любая помощь была бы оценена нами.

+0

Приведи http://stackoverflow.com/questions/18475195/there-is-already-an-open-datareader-associated-with-this-command-which-must-be- c/20535263 # 20535263 – Lijo

ответ

6

Как насчет того, чтобы вытащить данные в DataSet через Fill, а затем выполнить итерацию, чтобы выполнить вашу вставку через 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

не могли бы вы предоставить мне синтаксис или пример? – Pradeep

+0

@Pradeep, см. Выше; Я добавил несколько примеров кода. – Brad

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

Это не сработает - это то же самое, что и OP. –

+0

true, отредактировал мой ответ –

1

Какой версии SQL Server вы используете? Проблема может быть с этим:

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

При использовании версии SQL Server до того SQL Server 2005, в то время как SqlDataReader используется, связанный SqlConnection занят служа SqlDataReader. Хотя в этом состоянии никакие другие операции не могут выполняться в SqlConnection, кроме закрытия. Это происходит до тех пор, пока не вызывается метод Close для SqlDataReader.

Итак, если это то, что вызывает проблемы, вы должны сначала прочитать все данные, а затем закрыть 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) Получить все данные первым, либо с помощью DataSet или использовать читатель, чтобы заполнить некоторые другие коллекции, а затем запустить их все сразу после того, как первоначальный выбор сделан.

2) Используйте другое соединение для своих операторов вставки.

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

+1 для единственного ответа до сих пор, который безопасно распоряжается командами и считывателем – PHeiberg

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

Один оператор SQL вместо одного за вкладышем. Не уверен, что это будет работать для вашей реальной проблемы, но для примера, который вы предоставили, это гораздо лучший вопрос, чем выполнение по одному за раз.

На стороне примечания убедитесь, что ваш код использует параметризованные запросы вместо того, чтобы принимать строки как есть внутри оператора SQL - ваш образец открыт для SQL-инъекции.

80

Не нужно делать все это, просто включите MARS, и ваша проблема будет решена.В вашей строке подключения просто добавьте MultipleActiveResultSets=True;

+1

Проверено это с помощью SQL 2008. http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/78d3989a-8975-4930-998d-1eb907966f57 – user423430

+1

Работает для меня. SQL Server 2008. – finitenessofinfinity

+0

Работает для меня. SQL Server 2008. – Swag

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

Добавление это строки соединения должны решить эту проблему.

MultipleActiveResultSets=true 
0

Лучшее решение: Существует только проблема с значением "CommandText". Пусть это SP или обычный Sql Query.

  • Проверка 1: Значение параметра, который вы передаете в ваш запрос не меняется, и происходит то же самое снова и снова в вашем 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(); 
    
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() 
     }` 
+0

Неработающий код –

+0

Вы открыли соединение перед выполнением чтения? Вы уверены, что правильно читаете данные? –

+0

Да, но все равно нет результата –

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" /> 
Смежные вопросы

 Смежные вопросы