使用Statement和Lazy Initialized属性时出错

时间:2009-12-01 21:02:17

标签: vb.net using-statement

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

2 个答案:

答案 0 :(得分:1)

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

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

  1. 调用Load()
  2. Using语句调用Connection属性的Get
  3. _Connection设置为新的SqlConnection并返回
  4. 返回的连接已打开并正常使用
  5. 使用块退出,在连接上调用Dispose()
  6. 此时,SqlConnection对象仍然存在,并且仍由_Connection指向。它不再处于可用状态,因为它是Dispose()d。当第二次调用Load()进来时:

    1. 调用Load()
    2. Using语句调用Connection属性的Get
    3. _Connection仍然指向(无用的)SqlConnection对象,因此它不是Nothing,并且没有设置为新的SqlConnection对象
    4. 返回(无用的)连接
    5. 在连接上调用Open() - 它处于不可用状态 - 并触发InvalidOperationException
    6. 您正在混合使用冲突的连接管理方法。保持连接对象作为类的成员意味着您希望在SomeEntity对象的生命周期中保持连接活动,但使用Using意味着您希望在每次使用时动态创建和销毁连接。

答案 1 :(得分:0)

您的Connection语句中的

Using未被初始化或声明。您的代码应该更像:

Public Sub Load(ByVal key As Integer)
    Using myConnection as SqlClient.SqlConnection = Me.Connection
        Connection.Open()
            ...
    End Using
End Sub