ExecuteNonQuery покидает сеанс ожидания команды ожидания

У меня есть утилита командной строки, написанная на C#, которая обновляет некоторые записи в базе данных, затем входит в цикл, проверяя некоторые другие вещи. По какой-то причине выполнение SQL всегда оставляет сеанс ожидания команды ожидания в SQL Server 2008 после выполнения SQL. Я могу использовать монитор активности сервера SQL и запустить sp_who2, чтобы подтвердить это. Но транзакция SQL была успешно завершена. Я могу сказать это по отладке в коде, а также по отметке времени записи данных в базе данных. Кроме того, открытый спящий сеанс будет прерван, когда я явно остановлю утилиту командной строки. Кажется, это указывает на то, что моя функция создает некоторый объект соединения SQL, который не может быть удален до тех пор, пока CLR не соберет мусор, когда приложение будет прервано. Как такое могло произойти? Благодарю. Вот код:

bool result = false;
     using (SqlConnection conn = new SqlConnection(this.Connection))
     {

        using (SqlCommand cmd = conn.CreateCommand())
        {
           cmd.CommandText =
                 @"if not exists (select id from pl where sj=@sj and ej=@ej and dateInactivated is null) 
                       insert into pl(sj,ej,pf, br, tk, lastModified )
                       values(@sj,@ej,@pf,@br,@tk,getDate())
                    else
                       update pl set sj=@sj,ej=@ej,pf=@pf,br=@br,tk=@tk,lastModified=getDate()
                       where sj=@sj and ej=@ej and dateInactivated is null
                    ";

           cmd.Parameters.AddWithValue("@sj", sj);
           cmd.Parameters.AddWithValue("@ej", ej);
           cmd.Parameters.AddWithValue("@pf", pf);
           cmd.Parameters.AddWithValue("@br", br);
           cmd.Parameters.AddWithValue("@tk", tkData);
           cmd.CommandTimeout = 60;
           SqlTransaction trans = null;
           try
           {
              conn.Open();
              trans = conn.BeginTransaction();
              cmd.Transaction = trans;
              cmd.ExecuteNonQuery();
              trans.Commit();
              conn.Close();
              result = true;
           }
           catch (SqlException ex)
           {
              if (trans != null)
              {
                 trans.Rollback();
              }
              Log.WriteLog(LogLevel.ERROR, ex.Message);
              result = false;
           }
           finally
           {
              if (conn.State != ConnectionState.Closed)
              {
                 conn.Close();
              }
           }
        }

     }

     return result;

Обратите внимание, что поле tk является полем базы данных xml.

2 ответа

Решение

Это называется пул соединений, и вы хотите, чтобы он работал таким образом.

По сути, полное удаление соединения и его повторное установление для вашего приложения влечет за собой гораздо большие штрафы, чем повторное использование простаивающего соединения, которое было оставлено после предыдущего вызова вашего кода. Это хорошая вещь.

Это из-за объединения. В 99,99% случаев это здорово, так как меньше подключений выполняется и разрывается, а если многопоточность - одновременно меньше открытых соединений.

Если вы добавите Pooling=false к строке подключения, он не будет использоваться. Единственными причинами для этого являются:

  1. В качестве временной меры, если вы где-то пропускаете соединения в пуле - обратите внимание, что это ухудшает ситуацию с точки зрения производительности, но не влияет на максимальный размер пула. Сильный акцент на временном здесь.
  2. У вас есть клиентские приложения, совместно использующие базу данных и использующие соединения в течение очень небольшого промежутка времени. Здесь вы хотите отключить пул, потому что, хотя это делает каждого клиента менее эффективным, оно снижает нагрузку на сам сервер.

Второе очень редко. Первое должно быть очень редким - опять же акцент на временное.

Другие вопросы по тегам