January 27, 2005 at 2:02 pm
I have the following stored procedure which works just fine in QA, returning both the 280,000 row recordset and the corresponding count
CREATE PROCEDURE dbo.stp_ConvertCharges
@RecordCount int output AS
BEGIN
DECLARE @ReturnError int
SET NOCOUNT ON
SELECT chgCaseNumber, chgPartyNumber
FROM Cases sca
LEFT OUTER JOIN Charges sch ON
sca.CasCaseNumber = sch.ChgCaseNumber
LEFT OUTER JOIN CaseParty cp ON
sca.CasCaseNumber = cp.CaseID
LEFT OUTER JOIN uCaseType uCT ON
sca.CasCaseTypeCode = uCT.CaseUTypeID
INNER JOIN sCaseType sCT ON
uCT.CaseTypeKy = sCT.CaseTypeKy
LEFT OUTER JOIN uExtConn uEC ON
cp.ExtConnID = uEC.ExtConnID
LEFT OUTER JOIN uOffense uO ON
sch.ChgStatuteNum = uO.Statute
WHERE sCT.CaseCategoryKy = 'CR'
ORDER BY sca.CasCaseNumber
SELECT @RecordCount = @@RowCount, @ReturnError = @@Error
RETURN @ReturnError
END
GO
I have the following VB6 routine that attempts to run the stored procedure to return the recordset and the output parameters
Private Sub S030_RetrieveData()
Dim cmdSubCommand As ADODB.Command
m_intDataReturnError = 99
m_lngDataRecordCount = 99
Err.Clear
Set g_rsData = New ADODB.Recordset
g_rsData.CursorLocation = adUseClient
g_rsData.CursorType = adOpenStatic
g_rsData.LockType = adLockReadOnly
Set cmdSubCommand = New ADODB.Command
If Err.Number > 0 Then
Exit Sub
End If
With cmdSubCommand
.CommandType = adCmdStoredProc
.CommandTimeout = 300
.CommandText = "stp_ConvertCharges"
.ActiveConnection = strDBConnectionString
.Parameters.Append .CreateParameter("ReturnError", adInteger, adParamReturnValue)
.Parameters.Append .CreateParameter("RecordCount", adInteger, adParamOutput)
Set g_rsData = .Execute()
.ActiveConnection = Nothing
m_lngDataRecordCount = .Parameters("RecordCount").Value
m_intDataReturnError = .Parameters("ReturnError").Value
End With
MsgBox ("Record Count = " & m_lngDataRecordCount & " ReturnError = " & m_intDataReturnError)
Set cmdSubCommand = Nothing
End Sub
The VB returns the recordset just fine, but the output parameters both come back as zeroes. Can anyone see what's wrong with it?
Thanks.
MattieNH
January 27, 2005 at 2:22 pm
Did you try closing the connection before trying to access the parameters? I vaguely remember that you hav to CLOSE something (either the cn or rs but I'm pretty sure it's the cn) before you can access any output parameter.
But first I would run the sp in qa to make sure that the problem doesn't come from there. Then I would try closing the connection before trying to fetch the recordcount.
One other option would be not to use the set nocount on option and use the recordset recordcount property if possible.
January 27, 2005 at 2:36 pm
Thanks for responding. I'm not sure how to close the connection, since I don't explicitly create and open one in this routine. I did create a connection, use it to delete all the records from an exception table, and close it in a previous routine.
I've read that you have to close the recordset to access the output variables, and I tried that before retrieving the parameters, as in
g_rsData.close
m_lngSustainDataRecordCount = .Parameters("RecordCount").Value
m_intSustainDataReturnError = .Parameters("ReturnError").Value
End With
but that didn't work.
I have run the SP in Query Analyzer, and it works just fine. And with or without SET NOCOUNT ON, I can't get anything but a -1 for a record count.
What would the syntax be to close the implicit connection created by the command object?
MattieNH
January 27, 2005 at 2:43 pm
Hmm this can be a problem
.ActiveConnection = strDBConnectionString
You could try setting ActiveConnection to an adodb.connection object and close that object before accessing the params to see if it works.
As for the recordcount not working you'd have to change to cursor type or locktype... don't remember which one causes this behavior.
January 27, 2005 at 11:51 pm
You could try to open the recordset in an alternative way:
g_rsData.Open cmdSubCommand, , adOpenStatic, adLockReadOnly
Set g_rsData.ActiveConnection = Nothing
m_lngDataRecordCount = cmdSubCommand.Parameters("@RecordCount")
This does the trick in my applications.
Erik
January 28, 2005 at 6:07 am
Actually this is one of those gotcha items.
The OUPUT parameters are only available after the recordset is processed.
User a client side cursor and do a MoveLast then get your parameters and MoveFirst on the recordset, this should do it.
January 28, 2005 at 7:40 am
'Gotcha' is a polite term for what this is.
Part of me hates to ask this, but the part of me that's spent two days on this is desperate. Apparently I can't do a MoveLast because even though I explicitly open the recordset as client side (g_rsSustainData.CursorLocation = adUseClient), the command object will only open a ForwardOnly recordset with the Execute method. I know how to use the rs.open method, but not in conjunction with the the command object, which is the only way I know how to pass and retrieve parameters.
I would really appreciate it if you could show me exactly what the code should be to call a stored procedure with parameters and still return a dynamic recordset.
Thanks for all your help.
Mattie
January 28, 2005 at 7:54 am
You can't exactly do what you're doing in VB6. In .NET it might be Ok.
You should change your Procedure to this:
@Errors int output = 0
AS
BEGIN
SELECT chgCaseNumber, chgPartyNumber
FROM Cases sca
LEFT OUTER JOIN Charges sch ON sca.CasCaseNumber = sch.ChgCaseNumber
LEFT OUTER JOIN CaseParty cp ON sca.CasCaseNumber = cp.CaseID
LEFT OUTER JOIN uCaseType uCT ON sca.CasCaseTypeCode = uCT.CaseUTypeID
INNER JOIN sCaseType sCT ON uCT.CaseTypeKy = sCT.CaseTypeKy
LEFT OUTER JOIN uExtConn uEC ON cp.ExtConnID = uEC.ExtConnID
LEFT OUTER JOIN uOffense uO ON sch.ChgStatuteNum = uO.Statute
WHERE sCT.CaseCategoryKy = 'CR'
ORDER BY sca.CasCaseNumber
RETURN
END
SET NOCOUNT OFF
GO
And your VB Code should look like this:
On Error GoTo ErrHandler
Dim adoCon As ADODB.Connection
Dim adoCmd As ADODB.Command
Dim rsData As ADODB.Recordset
Dim nRecords As Long, nError As Long
'Open the Connection
Set adoCon = New ADODB.Connection
adoCon.Open sConnectString
'Initialize the Command
Set adoCmd = New ADODB.Command
With adoCmd
.CommandType = adCmdStoredProc
.CommandText = "spMyProc"
Set .ActiveConnection = adoCon
'There is no need to Add any Parameters
'The ADO Command Object intrinsicly knows the Parameters
'because it has a Connection to the Database
'The 'nRecords' variable will return the number of Records affected
'This eliminates the need for an Output Paramters telling you how many Records were affected
Set rsData = .Execute(nRecords)
nError = .Parameters("@Errors").Value
End With
While Not rsData.EOF
'Do something...
rsData.MoveNext
Wend
ErrHandler:
If (Err.Number <> 0) Then MsgBox Err.Description
'CleanUp
If (Not rsData Is Nothing) Then rsData.Close
If (Not adoCon Is Nothing) Then adoCon.Close
Set rsData = Nothing: Set adoCmd = Nothing: Set adoCon = Nothing
Also, DO NOT CLOSE the Connection until you are finished with the Recordset. Any Recordset opened through a Command Object will be ForwardOnly with a ServerSide Cursor. You cannot change that.
By using the ADODB.Connection variable, you are ensured that your connection will not close after the Command has been executed. Sure, it's one more variable to cleanup, but it's not that big a difference.
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply