使用语句和延迟初始化属性时出错

发布于 2024-08-13 16:50:04 字数 862 浏览 5 评论 0原文

下面的代码将抛出 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

The code below will throw an InvalidOperationException: The ConnectionString property has not been initialized. The exception is thrown at the line calling Connection.Open() in the Load method. If I use the try-finally statement instead of the using statement, everything works correctly. Can anyone explain why the exception occurs with the using statement?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剑心龙吟 2024-08-20 16:50:04

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

使用Using时,当Using块退出时,对使用的变量调用Dispose()。因此,在您的场景中:

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

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

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

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

You failed to mention a key piece of information: It succeeds the first time Load() is called, but then fails forever after.

When using Using, Dispose() is called on the used variable when the Using block exits. So in your scenario:

  1. Load() gets called
  2. The Using statement calls the Connection property's Get
  3. _Connection gets set to a new SqlConnection and returned
  4. The returned connection gets opened and used normally
  5. The Using block exits, calling Dispose() on the connection

At this point, the SqlConnection object still exists, and is still pointed to by _Connection. It's no longer in a usable state though, since it's been Dispose()d. When the second call to Load() comes in:

  1. Load() gets called
  2. The Using statement calls the Connection property's Get
  3. _Connection is still pointing to a (useless) SqlConnection object, therefore it's not Nothing, and doesn't get set to a new SqlConnection object
  4. The (useless) connection gets returned
  5. Open() gets called on the connection--which is in an unusable state--and triggers the InvalidOperationException

You're mixing conflicting approaches to connection management. Keeping the connection object around as a member of the class implies that you want to keep the connection alive for the life of the SomeEntity object, but using Using implies that you want to create and destroy the connection on the fly with each usage.

渡你暖光 2024-08-20 16:50:04

Using 语句中的 Connection 未初始化或声明。您的代码应该更像:

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

Connection in your Using statement is not being initialized or declared. Your code should read more like:

Public Sub Load(ByVal key As Integer)
    Using myConnection as SqlClient.SqlConnection = Me.Connection
        Connection.Open()
            ...
    End Using
End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文