0

下面的代码将抛出 InvalidOperationException:ConnectionString 属性尚未初始化。在 Load 方法中调用 Connection.Open() 的行会引发异常。如果我使用 try-finally 语句而不是 using 语句,则一切正常。谁能解释为什么使用语句会发生异常?

Public Class SomeEntity
    Private _Connection As SqlClient.SqlConnection
    Private _ConnectionString As String

    Protected ReadOnly Property Connection() As SqlClient.SqlConnection
        Get
            If _Connection Is Nothing Then
                _Connection = New SqlClient.SqlConnection(_ConnectionString)
            End If
            Return _Connection
        End Get
    End Property

    Public Sub New(ByVal connectionString As String)
        _ConnectionString = connectionString
    End Sub

    Public Sub Load(ByVal key As Integer)
        Using Connection
            Connection.Open()
            ...
        End Using
    End Sub
End Class
4

2 回答 2

1

您没有提到关键信息:第一次调用 Load() 时它成功,但之后永远失败。

使用 Using 时,在 Using 块退出时对已使用的变量调用 Dispose()。所以在你的场景中:

  1. Load() 被调用
  2. Using 语句调用 Connection 属性的 Get
  3. _Connection 设置为新的 SqlConnection 并返回
  4. 返回的连接被打开并正常使用
  5. Using 块退出,在连接上调用 Dispose()

此时,SqlConnection 对象依然存在,并且仍然被_Con​​nection 所指向。但它不再处于可用状态,因为它已被 Dispose()d。当第二次调用 Load() 时:

  1. Load() 被调用
  2. Using 语句调用 Connection 属性的 Get
  3. _Connection 仍然指向一个(无用的)SqlConnection 对象,因此它不是 Nothing,也没有设置为新的 SqlConnection 对象
  4. (无用的)连接被返回
  5. Open() 在连接上被调用——它处于不可用状态——并触发 InvalidOperationException

您正在混合相互冲突的连接管理方法。将连接对象保留为类的成员意味着您希望在 SomeEntity 对象的生命周期内保持连接处于活动状态,但使用 Using 意味着您希望在每次使用时动态创建和销毁连接。

于 2009-12-01T22:02:15.483 回答
0

Connection在您的Using声明中没有被初始化或声明。您的代码应该更像:

Public Sub Load(ByVal key As Integer)
    Using myConnection as SqlClient.SqlConnection = Me.Connection
        Connection.Open()
            ...
    End Using
End Sub
于 2009-12-01T21:20:25.773 回答