2013-10-08 3 views
0

Привет Я создаю элементы управления из SQL с помощью этого кода:InvalidOpearationException: Существует уже открытая DataReader

string query = "SELECT * FROM [schema] WHERE [email protected]"; 
      SqlCommand com = new SqlCommand(query, con); 
      com.Parameters.AddWithValue("@id", result); 
      con.Open(); 
      SqlDataReader read= com.ExecuteReader(); 

      while (read.Read()) 
      { 

       createLabelCmd((int)read["x"], (int)read["y"]); 


      } 
      con.Close(); 

Вопрос заключается в том, что createLabelCmd содержит SqlCommand и нуждается в открытой SqlConnection

Внутри createLabelCmd

String ResultSitting 
private void createLabelCmd(int x, int y) 
    { 
for (int i = 0; i < 1; i++) 
     { 
      var newLabel = new Label(); 
      newLabel.Location = new Point(x, y); 
      newLabel.Text = realpocsed.ToString(); 
      string sitting = newLabel.Name; 
      string sittingSearch = (sitting).Substring(3, 1); 
      if (sittingSearch != null && kzajezdu == "kZajezdu") 
      { 
       string querySitting = "SELECT name, surname FROM klient WHERE sitting = @sitting AND [email protected] AND [email protected]"; 
       SqlCommand cmdSitting = new SqlCommand(querySitting, spojeni); 
       cmdSitting.Parameters.AddWithValue("@sitting", sittingSearch); 
       cmdSitting.Parameters.AddWithValue("@event", idEvent); 
       cmdSitting.Parameters.AddWithValue("@year", klientClass.Year()); 

       ResultSitting = cmdSitting.ExecuteScalar().ToString().Trim(); //This might be the issue 

      } 

      if (kzajezdu == "kZajezdu") 
      { 
       newLabel.MouseHover += delegate(object sender, EventArgs e) 
       { 
        ToolTip ToolTip1 = new ToolTip(); 
        ToolTip1.ShowAlways = true; 
        if (sittingSearch != null) 
        { 
         ToolTip1.Show(ResultSitting, newLabel); 
        } 
        else { ToolTip1.Show("This sitting is Empty!", newLabel); } 
       }; 

      } 

      panel1.Controls.Add(newLabel); 
     } 

Получаю исключение: InvalidOpearationException: There is already an open DataReader associated with this Command which must be closed first.

Можете ли вы помочь мне решить эту проблему?

Редактировать как Сонер Gönül предложил:

try 
     { 
      string query = "SELECT * FROM [schema] WHERE [email protected]"; 
      SqlCommand com = new SqlCommand(query, con); 
      com.Parameters.AddWithValue("@id", idSch); 
      con.Open(); 
      SqlDataReader read= com.ExecuteReader(); 

      while (precti.Read()) 
      { 
       createLabelCmd((int)read["x"], (int)read["y"]); 

      } 
      con.Close(); 
     } 
+0

@TimSchmelter Спасибо за этот вопрос. Надеюсь, что это не проблема с открытым DataReader. – Marek

+0

Я удалил свой комментарий, так как заметил, что он действительно работает, чтобы выбрать несколько столбцов с помощью 'ExecuteScalar'. Кажется, что 'SqlCommand' выбирает просто первый столбец. Однако это не лучшая практика. –

+0

На какой линии вы получаете сообщение об ошибке? – Rezoan

ответ

2

Причина проблемы описана в других ответах (в то время как DataReader открыт, соединение, используемое этим считывателем, не может обслуживать другие команды), однако многие не могут говорить о MultipleActiveResultSets, который был введен для таких ситуаций

Просто измените строку подключения, чтобы включить эту опцию, и ваш код будет работать без каких-либо изменений

Server=yourServer;Database=yourDB;Trusted_Connection=True;MultipleActiveResultSets=true; 

чтобы завершить ответ, MARS доступен, начиная с SQL Server 2005 и there are minor problems, что вы должны знать.

2

Потому что, когда вы в то время как петли с открытым SqlDataReader, есть открытое соединение уже.

От DataReaders (ADO.NET)

«Вы можете использовать ADO.NET DataReader для извлечения только для чтения, однонаправленного потока данных из базы данных.

Результаты возвращаются как запрос выполняется, и хранятся в сетевом буфере на клиенте, пока вы не отправите их, используя метод DataReader»

В общей Рекомендации для чтения , используйте using как ;

using(SqlDataReader read= com.ExecuteReader()) 
{ 
    while (read.Read()) 
    { 
     createLabelCmd((int)read["x"], (int)read["y"]); 
    } 
} 

Или установите это в своей строке подключения;

...MultipleActiveResultSets=true; 
+0

Я заменил часть моего кода, как вы предложили (вы можете видеть в моем редактировании), но все же получили то же Исключение. Можете ли вы мне помочь? – Marek

1

Я думаю, вы пишете сидящего планировщика и пытаетесь показать ярлыки на определенных позициях. Поэтому вам лучше выбрать все записи из таблицы klient для данного события и поместить их в DataSet. Затем проведите по ней (используя foreach) и создайте метки. Таким образом, только одна команда должна быть отправлена ​​в базу данных, и, очевидно, производительность вашего приложения будет намного лучше.

Сказав это, я не понимаю, как работает ваша переменная sittingSearch, и я думаю, что она нуждается в пересмотре.

1

Вы можете либо использовать второе соединение для createLabelCmd, либо включить MARS (несколько активных наборов результатов) в своем первоначальном соединении, добавив в строку соединения «MultipleActiveResultSets = True».

http://msdn.microsoft.com/en-us/library/h32h3abf.aspx

0

Настройка MARS Истина и убедившись, что я использовал ToList(); в моих операциях if и возвращает в приведенном ниже коде, мне не хватало toList() в обоих условиях оператора if, я получал сообщение об ошибке в IIS 8.5 после публикации. Обновление инструкции к приведенному ниже @!

var varM = (id == 1) ? db.M.Where(x => x.UN== userID).ToList() : db.M.Where(x => x.EUN== userID).ToList(); 
Смежные вопросы