简体   繁体   中英

Returning a value from SQL Server to VB.Net

How do I pass @attackPercentage back to my VB procedure and have it read by the reader? I keep getting an error:

System.IndexOutOfRangeException: attackPercentage

Code:

ALTER PROCEDURE [dbo].[SelectPlayersRating]
    @playerAccountID uniqueidentifier,
    @raterAccountID uniqueidentifier
AS
BEGIN
    DECLARE @attackPercentage INT

    SELECT attack, safety, consistency 
    FROM tblRatings 
    WHERE @playerAccountID = playerAccountID 
      AND @raterAccountID = raterAccountID

    SET @attackPercentage = '99' --Test Value

    RETURN @attackPercentage 
END

VB.NET code:

Dim DBConnect3 As New DBConn

Using db As DbConnection = DBConnect3.Conn("DBConnectionString")

    Dim cmd As SqlCommand = DBConnect3.Command(db, "SelectPlayersRating")
    cmd.Parameters.Add(New SqlParameter("playerAccountID", SqlDbType.UniqueIdentifier, ParameterDirection.Input)).Value = Guid.Parse(Request.QueryString("aID"))
    cmd.Parameters.Add(New SqlParameter("raterAccountID", SqlDbType.Uniqueidentifier, ParameterDirection.Input)).Value = acc.accountID

    db.Open()

    Dim DR As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)

    While DR.Read
        ddlAttack.SelectedValue = DR("attack")
        ddlSafety.SelectedValue = DR("safety")
        ddlConsistency.SelectedValue = DR("consistency")
        session("test") = DR("attckPercentage")
    End While

    DR.Close()
    DR = Nothing
    cmd.Dispose()
    cmd = Nothing
    db.Dispose()
    db.Close()
End Using

Based on your stored procedure, your query can return multiple results, hence your While DR.Read statement.

However, your value for attackPercentage will return one value every time the stored procedure is returned. So you can use an Output Parameter to extract the value from the stored procedure:

ALTER PROCEDURE [dbo].[SelectPlayersRating]
@playerAccountID uniqueidentifier,
@raterAccountID uniqueidentifier
, @attachPercentage INT output --  This is the new output parameter
AS
BEGIN
-- DECLARE @attackPercentage INT -- remove the declaration as we've defined it already

SELECT attack, safety, consistency 
FROM tblRatings 
WHERE @playerAccountID = playerAccountID 
  AND @raterAccountID = raterAccountID

SET @attackPercentage = '99' --Test Value

-- RETURN @attackPercentage  -- No need to return this value
END

So now, how do you get the return value? Just add an output parameter to your parameter collection:

  Dim cmd As SqlCommand = DBConnect3.Command(db, "SelectPlayersRating")
cmd.Parameters.Add(New SqlParameter("playerAccountID", SqlDbType.UniqueIdentifier, ParameterDirection.Input)).Value = Guid.Parse(Request.QueryString("aID"))
cmd.Parameters.Add(New SqlParameter("raterAccountID", SqlDbType.Uniqueidentifier, ParameterDirection.Input)).Value = acc.accountID
cmd.Parameters.Add(New SqlParameter("attackPercentage", SqlDbType.Int, ParameterDirection.Output))

After your call to ExecuteReader, you can simply say:

session("test") = cmd.Parameters("attackPercentage").Value

I removed the return value.

ALTER PROCEDURE [dbo].[SelectPlayersRating]

    @playerAccountID uniqueidentifier,
    @raterAccountID uniqueidentifier

    AS
    BEGIN

        SELECT attack, safety, consistency FROM tblRatings WHERE        playerAccountID = @playerAccountID AND 
    raterAccountID = @raterAccountID  

    END

This is apparently a web application. I happen to be in WinForms at the moment but this would be same in a web app, just a different events signature. Just send the parameter values to the function and then use the returned datatable.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim dt = GetAttackData(Guid.Parse(Request.QueryString("aID")), acc.accountID)
    ddlAttack.SelectedValue = dt(0)("attack")
    ddlSafety.SelectedValue = dt(0)("safety")
    ddlConsistency.SelectedValue = dt(0)("consistency")
    session("test") = 99 'You can calculate this here instead of the stored procedure
End Sub

I am not sure why you are using a DbConnection for Sql Server. Don't get a connection from somewhere else. A connection needs to be closed and disposed so use a local variable.

Private Function GetAttackData(aId As Guid, accID As Guid) As DataTable
    Using dt As New DataTable
        Using db As New SqlConnection(ConStr),
        cmd As New SqlCommand("SelectPlayersRating", db)
            cmd.CommandType = CommandType.StoredProcedure
            cmd.Parameters.Add("playerAccountID", SqlDbType.UniqueIdentifier).Value = aId
            cmd.Parameters.Add("raterAccountID", SqlDbType.UniqueIdentifier).Value = accID
            db.Open()
            Using DR As SqlDataReader = cmd.ExecuteReader()
                dt.Load(DR)
            End Using
        End Using
        Return dt
    End Using
End Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM