SqlDataReader - 多个连接

时间:2011-10-26 15:11:28

标签: sql-server vb.net sqldatareader

我在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

batchRevbatchID都是模块中的全局变量。

在行为:

  • 应用程序打印出“1”(用户输入),“1”(数据库结果),“0”(已关闭连接的枚举)
  • 当我按 Enter 超过第一个Console.ReadLine()时,该应用只会关闭。

如果我注释掉GetBatchRevision并直接设置batchRev = 1,我会得到上述结果以及“执行测试脚本1修订版52”,“执行测试脚本2修订版66”这些是预期的存储过程GetTestScriptsInTestBatch的结果。

全局变量声明如下:

Private batchID As String

Private batchRev As String

GetBatchRevision()导致应用崩溃的任何想法?它本身(删除存储的代码部分),执行得很好。我最初的猜测是有一个挂起连接,但是结束“使用”块应该关闭SQL连接以及与所述连接相关联的任何打开的读取器(如前所述,cs.State返回0)。

2 个答案:

答案 0 :(得分:2)

您的问题出在以下几行:

 reader.Read()

 If Not IsDBNull(reader(0)) Then

reader.Read()可能会返回false;但您尝试访问reader(0)。吊杆!

您应将其更改为:

IF reader.Read() AndAlso Not IsDBNull(reader(0)) Then
    '' etc
End If

答案 1 :(得分:1)

看起来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而不是内部字符串,这可以变得更好。