未找到结果时,SqlHelper.ExecuteReader()抛出异常

时间:2015-07-02 15:35:50

标签: sql-server vb.net exception-handling indexoutofboundsexception executereader

我有一个声明如下的SqlDataReader:

Dim myReader As SqlDataReader
myReader = SqlHelper.ExecuteReader(ConnectionString, "storedProcedure1", CInt(myTextBox.Text))

后来我使用这样的结果:

If myReader.HasRows Then
    While myReader.Read()
            Row = Table1.NewRow()
            Row.Item("REF") = myReader.GetString(0)
            Row.Item("CD") = myReader.GetString(1)
            Row.Item("NAME") = myReader.GetString(2)
            Row.Item("KEY") = myReader.GetDecimal(3)
            Row.Item("STRING") = myReader.GetString(0) & " - " & myReader.GetString(1) & " - " & myReader.GetString(2).ToString().Replace("'", "") & " - " & myReader.GetString(4).ToString().Replace("'", "")

            Table1.Rows.Add(Row)

            'Fill Drop Down
            drpMenu.Items.Add(New ListItem(myReader.GetString(0) & " - " & myReader.GetString(1) & " - " & myReader.GetString(2).ToString().Replace("'", "") & " - " & myReader.GetString(4).ToString().Replace("'", "")))
    End While
End If

myTextBox是一个文本框,用户输入可能使用存储过程搜索的位置编号。如果用户输入有效的位置编号,这很好用,我没有问题。如果他们输入一个不存在的位置编号,我会得到一个例外:

  

System.IndexOutOfRangeException:索引超出了数组的范围。

我认为If myReader.HasRows行会阻止我尝试阅读和操纵不存在的结果,但必须有一些我遗漏的东西。 myTextBox已经在代码的其他地方进行了验证,以确保用户输入的整数没有任何古怪的字符,因此输入错误似乎也不是问题。

在致电SqlHelper.ExecuteReader()之前,如何确定位置号码是否存在?或者更好的问题是如何优雅地处理此异常并告诉用户未找到位置?

编辑:这是存储过程。

ALTER PROCEDURE [dbo].[storedProcedure]
    -- Add the parameters for the stored procedure here
    @MBR as  integer
AS
BEGIN 
    EXEC ('{CALL RM#IMLIB.spGETLOC( ?)}', @MBR) at AS400
END 

编辑#2:当我在SMS中运行存储过程并传递有效位置时,它会返回我期望的内容。如果我传递了无效的位置编号,则不返回任何内容。

2 个答案:

答案 0 :(得分:2)

首先。创建一个局部变量...并将文本框值转换为局部变量...以确保这不是错误。

dim myValue as Int32
myValue = '' convert textbox value to an int.

第二......通常,我的datareader代码看起来像这样。

    If (Not ( reader Is Nothing) ) then
        If reader.HasRows Then 
            Do While reader.Read()
                Console.WriteLine(reader.GetInt32(0) _
                  & vbTab & reader.GetString(1))
            Loop 
        End If
    End If

(当然,您必须根据具体情况调整GetInt32或GetString和序号)。

我的猜测是你的子程序(RM#IMLIB.spGETLOC)中有逻辑,如果没有匹配则不会返回一行。

您仍然可以返回没有行的结果.... **(再次阅读)。

例如

Select ColA, ColB from dbo.MyTable where 0=1

这将返回一个没有行的结果。这与不返回(ny)select语句不同..(再次阅读)

我的猜测是,这个小小的细微差别是你遇到问题的地方。

APPEND:

如果您无法更改子存储过程....

创建一个#TempTable ...... 使用子存储过程填充#TempTable。 从#TempTable中选择。

以下是一个通用示例:

    IF OBJECT_ID('tempdb..#TempOrders') IS NOT NULL
    begin
            drop table #TempOrders
    end


    CREATE TABLE #TempOrders
    ( 
        ColumnA int
      , [ColumnB] nchar(5)

    )

/* Note, your #temp table must have the exact same columns as returned by the child procedure */

INSERT INTO #TempOrders ( ColumnA, ColumnB )
exec dbo.uspChildProcedure ParameterOne

Select ColumnA, ColumnB from #TempOrders






    IF OBJECT_ID('tempdb..#TempOrderDetails') IS NOT NULL
    begin
            drop table #TempOrderDetails
    end

答案 1 :(得分:1)

我终于找到了我的问题。

稍后在我的代码中,如果找不到位置,我有一个DataRow数组为空。我得到了异常,因为它试图从数组(0)中获取一个完全正确的项目。

我最初错过了它,因为我认为它是DataRow,而不是DataRow数组。伙计,我讨厌修理我没写过的代码...