我在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
都是模块中的全局变量。
在行为:
Console.ReadLine()
时,该应用只会关闭。如果我注释掉GetBatchRevision
并直接设置batchRev = 1
,我会得到上述结果以及“执行测试脚本1修订版52”,“执行测试脚本2修订版66”这些是预期的存储过程GetTestScriptsInTestBatch
的结果。
全局变量声明如下:
Private batchID As String
Private batchRev As String
为GetBatchRevision()
导致应用崩溃的任何想法?它本身(删除存储的代码部分),执行得很好。我最初的猜测是有一个挂起连接,但是结束“使用”块应该关闭SQL连接以及与所述连接相关联的任何打开的读取器(如前所述,cs.State返回0)。
答案 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而不是内部字符串,这可以变得更好。