2009-12-01 3 views
0

Код ниже будет вызывать InvalidOperationException: свойство ConnectionString не было инициализировано. Исключение выбрано в строке вызова метода Connection.Open() в методе Load. Если я использую инструкцию 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 

ответ

0

Connection в вашем Using заявлении не инициализируется или объявлены. Ваш код должен прочитать больше как:

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

Собственно, это так. Он относится к защищенному свойству Connection класса SomeEntity. –

1

Вы не упомянули ключевую часть информации: Он преуспевает в первый раз Load() вызывается, но не может навсегда после.

При использовании Use, Dispose() вызывается в используемой переменной при выходе из блока использования. Так что в вашем случае:

  1. Load() вызывается
  2. Применение метода оператор называет свойство Connection Надевать
  3. _Connection получает значение нового SqlConnection и вернулся
  4. Возвращенный соединение получает открыт и используется обычно
  5. в Использование блока выходит, вызов Dispose() на соединении

на данный момент, SqlConnection объективистские t все еще существует и по-прежнему указывается на _Connection. Он больше не находится в состоянии использования, поскольку это был Dispose() d. Когда второй вызов Load() приходит в:

  1. Load() вызывается
  2. Применение метода оператор называет свойство Connection Надевать
  3. _Connection все еще указывает на (бесполезный) объект SqlConnection, поэтому это не ничего и не приготовьтесь к новому объекту SqlConnection
  4. The (бесполезное) соединение получает возвращенный
  5. Open() вызывается на связи - что в нерабочем состоянии - и запускает InvalidOperationException

Вы смешиваете конфликтующие подходы к управлению соединениями. Сохранение объекта соединения как члена класса подразумевает, что вы хотите сохранить соединение живым для жизни объекта SomeEntity, но использование «Использование» подразумевает, что вы хотите создавать и уничтожать соединение «на лету» с каждым использованием.