Мое приложение требует от пользователя входа в систему и позволяет ему редактировать список вещей. Однако, похоже, что если один и тот же пользователь всегда входит в систему и редактирует список, он столкнется с «System.Data.SqlClient.SqlException: Timeout expired». ошибка. Я прочитал комментарий об этом, возможно, вызванный незафиксированными транзакциями. И у меня есть один входящий в приложение.
Я предоставлю код, с которым я работаю, и там есть оператор IF, в котором я немного сомневался, но это казалось разумным.
Я просто расскажу, что здесь происходит, есть список объектов, которые нужно обновить или добавить в базу данных. Новым объектам, созданным в приложении, присваивается идентификатор 0, в то время как существующие объекты имеют свои собственные идентификаторы, генерируемые из БД. Если пользователь решает удалить некоторые объекты, их идентификаторы хранятся в отдельном списке целых чисел. Как только пользователь готов сохранить свои изменения, два списка передаются в этот метод. С помощью оператора IF добавляются объекты с идентификатором 0 (с использованием хранимой процедуры Add), а объекты с ненулевыми идентификаторами обновляются (с использованием хранимой процедуры Update). После всего этого цикл FOR проходит через все целые числа в списке «удаления» и использует хранимую процедуру Delete для их удаления. Для всего этого используется транзакция.
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 поможет. Мне интересно, есть ли какие-либо большие недостатки или последствия от этого.