2010-05-10 4 views
0

Мое приложение требует входа пользователя и позволяет редактировать список вещей. Однако кажется, что если один и тот же пользователь всегда входит в систему и выходит из него и редактирует этот список, этот пользователь будет запускаться в «System.Data.SqlClient.SqlException: Timeout истек». ошибка. Я прочитал комментарий об этом, возможно, вызванный незафиксированными транзакциями. И у меня есть одно приложение.Возможная утечка соединения, вызывающая ошибку «System.Data.SqlClient.SqlException: Timeout expired» в SQL Server?

Я предоставлю код, с которым я работаю, и там есть утверждение IF, в котором я был немного немного, но это казалось разумным делом.

Я просто расскажу, что здесь происходит, есть список объектов для обновления или добавления в базу данных. Новым объектам, созданным в приложении, присваивается идентификатор 0, а существующие объекты имеют собственные идентификаторы, созданные из БД. Если пользователь хочет удалить некоторые объекты, их идентификаторы хранятся в отдельном списке целых чисел. После того, как пользователь готов сохранить свои изменения, два списка передаются в этот метод. С помощью оператора IF добавляются объекты с идентификатором 0 (с использованием Add хранимой процедуры), и те объекты с ненулевыми идентификаторами обновляются (используя хранимую процедуру Update). После этого цикл FOR проходит через все целые числа в списке «удаление» и использует удаление хранимой процедуры для их удаления. Для этого используется транзакция.

Public Shared Sub UpdateSomethings(ByVal SomethingList As List(Of Something), ByVal RemovalList As List(Of Integer)) 
Using DBConnection As New SqlConnection(conn) 
    DBConnection.Open() 
    Dim MyTransaction As SqlTransaction 
    MyTransaction = DBConnection.BeginTransaction() 
    Try 
     Using MyCommand As New SqlCommand() 
      MyCommand.Transaction = MyTransaction 
      MyCommand.CommandType = CommandType.StoredProcedure 

      For Each SomethingItem As Something In SomethingList 
       MyCommand.Connection = DBConnection 
       If SomethingItem.ID > 0 Then 
        MyCommand.CommandText = "UpdateSomething" 
       Else 
        MyCommand.CommandText = "AddSomething" 
       End If 
       MyCommand.Parameters.Clear() 
       With MyCommand.Parameters 
        If MyCommand.CommandText = "UpdateSomething" Then 
         .Add("@id", SqlDbType.Int).Value = SomethingItem.ID 
        End If 
        .Add("@stuff", SqlDbType.Varchar).Value = SomethingItem.Stuff 
       End With 
       MyCommand.ExecuteNonQuery() 
      Next 

      MyCommand.CommandText = "DeleteSomething" 
      For Each ID As Integer In RemovalList 
       MyCommand.Parameters.Clear() 
       With MyCommand.Parameters 
        .Add("@id", SqlDbType.Int).Value = ID 
       End With 
       MyCommand.ExecuteNonQuery() 

      Next 
     End Using 
     MyTransaction.Commit() 
    Catch ex As Exception 
     MyTransaction.Rollback() 
     'Exception handling goes here ' 
    End Try 

End Using 
End Sub 

Есть три хранимые процедуры, используемые здесь, а также некоторые зацикливания, так что я могу видеть, как можно что-то держит все вверх, если список достаточно велик.

Я использую Visual Studio 2008 для отладки и использую SQL Server 2000 для БД.

Редактировать: Я все еще, кажется, получаю эту ошибку. Я даже удалил всю транзакционную вещь, и я все еще сталкиваюсь с ней. На этом этапе я предполагаю, что здесь происходит какая-то утечка. Я пробовал не использовать USING-заявления и явно сообщать команде и подключению себя, но не кубиками. Использование памяти с помощью SQL Server также очень сильно возрастает, если этот метод называется много за короткий промежуток времени.

Я читал, что увеличение свойства CommandTimeout SQLCommand поможет. Мне интересно, есть ли большие недостатки или последствия от этого.

+0

BTW, я думаю, вы должны добавить «Rethrow» после откат в предложении catch. Вы на самом деле не исключали _handled_ исключение, поэтому вы должны разрешить его распространять. –

+0

Я, должно быть, случайно удалил обработку исключений из образца, который я разместил, но спасибо, что указал на это. :) – Michael

ответ

1

Я считаю, что мне удалось решить проблему. Я изменил приложение, чтобы ненужные вызовы в базу данных не были сделаны (т. Е. Неизменные объекты не нуждаются в повторном обновлении) и увеличено свойство CommandTimeout для объекта SQLCommand. До сих пор никаких проблем.

Большое спасибо за предложения.

1

Я предлагаю использовать следующее, таким образом, Dispose всегда будет вызываться и быть обратным в каждом случае без обязательства.

using (SqlConnection sqlCn = new SqlConnection()) 
{ 
    using (SqlTransaction myTrans = sqlCn.BeginTransaction()) 
    { 
    ... 
    myTrans.Commit(); 
    } 
} 

Кроме того, я не считаю, что вам нужно создать новый SqlCommand для каждого исполнения. Просто сохраните один и обновите CommandText и Parameters.

+0

Спасибо за предложение. Я посмотрю, решит ли это проблему, поскольку это имеет смысл. – Michael

1

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

Вы, вероятно, хотите использовать TransactionScope

Using _tx as New System.Transactions.TransactionScope(<add your own timeout here>) 

'Do all your sql work' 

If _noErrors Then 
    _tx.Complete() 
End If 

End Using 

С объемом транзакций, вы можете установить тайм-аут до 20 минут без изменения настроек сервера.

+0

Есть ли недостаток в увеличении периода ожидания на столько времени? Это повлияет на производительность? – Michael

+0

Да. При любой транзакции, чем дольше она будет открыта, тем больше ресурсов, которые она использует, блокируются из других процессов. Как правило, с базой данных вы хотите потратить как можно меньше времени на открытое соединение (следовательно, сначала создать все объекты команд). Существуют и другие способы пакетного SQL (данные библиотеки Ms Enterprise - http://msdn.microsoft.com/en-us/library/ff380164(v=PandP.31).aspx), которые могут работать еще лучше для вас. – StingyJack

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