SqlDataReader - несколько соединений - PullRequest
1 голос
/ 26 октября 2011

Я написал консольное приложение в VB.NET для работы с базой данных, и возникла странная ошибка во время выполнения ...

Вот основной код:

Sub Main(ByVal args() As String)
        Try
            user = args(0)
            batchID = args(1)

            GetBatchRevision()
            'batchRev = 1

            Dim getTestScripts As SqlCommand = New SqlCommand("GetTestScriptsInTestBatch", cs)
            getTestScripts.CommandType = CommandType.StoredProcedure

            Dim batchIDParam As SqlParameter = getTestScripts.Parameters.Add("@batchID", SqlDbType.Int, 4)
            Dim batchRevParam As SqlParameter = getTestScripts.Parameters.Add("@batchRev", SqlDbType.Int, 4)

            'batchIDParam.Value = 1
            'batchRevParam.Value = 1
            batchIDParam.Value = batchID
            batchRevParam.Value = batchRev

            Console.WriteLine(batchID & " " & batchRev)
            Console.WriteLine(cs.State)
            Console.ReadLine()

            Using cs
                cs.Open()
                Dim reader As SqlDataReader = getTestScripts.ExecuteReader(CommandBehavior.CloseConnection)

                While reader.Read()
                    Console.WriteLine("Executing Test Script " & reader("ScriptID").ToString() & " Revision " & reader("ScriptRev").ToString)
                End While

                Console.ReadLine()
            End Using

        Catch ex As Exception
        End Try
    End Sub

GetBatchRevision:

Private Sub GetBatchRevision()
    Using cs
        Dim GetNewestRev As New SqlCommand("SELECT Max(BatchRev) FROM TestBatch WHERE BatchID=" & batchID, cs)
        cs.Open()
        Dim reader As SqlDataReader = GetNewestRev.ExecuteReader(CommandBehavior.CloseConnection)
        reader.Read()

        If Not IsDBNull(reader(0)) Then
            batchRev = reader(0).ToString()
        End If
    End Using

End Sub

batchRev и batchID являются глобальными переменными внутри модуля.

Поведенческий:

  • Приложение выводит «1» (пользовательский ввод), «1» (результат базы данных), «0» (перечисление закрытого соединения)
  • Когда я нажимаю Введите , чтобы пройти первый Console.ReadLine(), приложение просто закрывается.

Если я закомментирую GetBatchRevision и сразу установлю batchRev = 1, я получу вышеуказанный результат, а также «Выполнение сценария теста 1 редакция 52», «Выполнение сценария теста 2 редакция 66», которые являются ожидаемыми результатами от сохраненного процедура GetTestScriptsInTestBatch.

Глобальные переменные декларируются следующим образом:

Private batchID As String

Private batchRev As String

Есть идеи, почему GetBatchRevision() вызывает сбой приложения? Сам по себе (удаляя сохраненную часть кода proc), он выполняется просто отлично. Первоначально я предполагал, что было зависшее соединение, но завершение блока «using» должно закрыть соединение SQL, а также все открытые программы чтения, связанные с указанным соединением (как упоминалось ранее, cs.State возвращает 0).

Ответы [ 2 ]

2 голосов
/ 26 октября 2011

Ваша проблема в следующих строках:

 reader.Read()

 If Not IsDBNull(reader(0)) Then

reader.Read() вероятно возвращает false; все же вы пытаетесь получить доступ к reader(0). Boom!

Вы должны изменить его на:

IF reader.Read() AndAlso Not IsDBNull(reader(0)) Then
    '' etc
End If
1 голос
/ 26 октября 2011

Похоже, cs также является глобальной переменной.Это плохая идея.Доступ к данным .Net работает намного лучше, когда вы используете новое соединение каждый раз.Вы, вероятно, хорошо в этом приложении, но вы настраиваете некоторые вредные привычки.Вместо этого загрузите строку подключения как глобальную переменную и используйте ее при создании подключений.

Далее, у GetBatchRevision() нет причин для общения с глобальными переменными.Пусть он примет аргумент и вернет его результат.И, конечно, я не могу не заметить проблему внедрения SQL-кода, потому что вы объединяете batchid до конца вашей строки.Вот новая версия функции после исправления этих ошибок:

Private Function GetBatchRevision(ByVal BatchID As String) As String
    Using cn As New SqlConnection(cs), _
          GetNewestRev As New SqlCommand("SELECT Max(BatchRev) FROM TestBatch WHERE BatchID= @BatchID", cn)

        GetNewestRev.Parameters.Add("@Batch", SqlDbType.Int).Value = Convert.ToInt32(BatchId)

        cn.Open()
        Return GetNewestRev.ExecuteScalar().ToString() 
    End Using

End Function

Это может стать еще лучше, если вы сохраните BatchRev и BatchID как int, а не как внутренние строки.

...