【发布时间】:2011-02-17 19:39:36
【问题描述】:
我的应用程序要求用户登录并允许他们编辑内容列表。但是,似乎如果同一个用户总是登录和注销并编辑列表,这个用户会遇到“System.Data.SqlClient.SqlException: Timeout expired”。错误。我已经阅读了可能由未提交的事务引起的评论。我确实有一个在申请中。
我将提供我正在使用的代码,其中有一个 IF 语句,我对此有点怀疑,但这似乎是一个合理的做法。
我将简单介绍一下这里发生的情况,有一个要更新或添加到数据库中的对象列表。在应用程序中创建的新对象的 ID 为 0,而现有对象具有从数据库生成的自己的 ID。如果用户选择删除某些对象,它们的 ID 将存储在单独的整数列表中。一旦用户准备好保存他们的更改,这两个列表就会传递给这个方法。通过使用 IF 语句,添加 ID 为 0 的对象(使用 Add 存储过程)并更新那些 ID 非零的对象(使用 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 用于 DB。
编辑:我似乎仍然收到此错误。我什至删除了整个交易的东西,我仍然遇到它。在这一点上,我假设这里发生了某种泄漏。我试过不使用 USING 语句并明确告诉命令和连接自行处理,但没有骰子。如果在短时间内大量调用此方法,SQL Server 的内存使用量也会增加不少。
我读到增加 SQLCommand 的 CommandTimeout 属性会有所帮助。我想知道这样做是否有什么大的缺点或后果。
【问题讨论】:
-
顺便说一句,我认为您应该在 catch 子句的回滚后添加一个
Rethrow。您实际上还没有处理异常,因此您应该允许它传播。 -
我一定是不小心删除了我发布的示例中的异常处理,但感谢您指出。 :)
标签: vb.net transactions sql-server-2000 timeout