Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > Visual Basic > VB 6 Visual Basic 6 > Pro VB Databases
Password Reminder
Register
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
Pro VB Databases Advanced-level VB coding questions specific to using VB with databases. Beginning-level questions or issues not specific to database use will be redirected to other forums.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Pro VB Databases section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developersí questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old March 15th, 2004, 03:56 PM
Friend of Wrox
 
Join Date: Jun 2003
Location: McPherson, Kansas, USA.
Posts: 128
Thanks: 0
Thanked 0 Times in 0 Posts
Default Stored Proc returns closed recordset ?

Can anyone point me in the right direction?

For some reason the stored proc is returning a closed recordset. The proc is executing and updating the table but for a reason unknown to me the recordset object is closed and errors out when I try to read it.

/ ************************************************** ****

    Dim rs As ADODB.Recordset
    Dim lError As Long
    Dim strError As String

    On Error GoTo ErrorHandler

    Set rs = gCn.Execute("Exec bsp_sRefSeed")
    ' Test for results
    ' Code is raising an error here
    If rs.BOF And rs.EOF Then
        ' Records where not found
        sRef = 0
    Else
        ' Return the sRef number
        sRef = rs!Seed
    End If

     etc ...

/ ************************************************** **
Stored Proc

USE BPROSCHD

GO

CREATE PROC bsp_sRefSeed

AS

/*
This proc will read the seed value
increment the seed value, and return the
value that was read.

This will ensure that no two parts receive the
same sRef number.

The seed value can only be 1 - 9999
*/

    Declare @Val int

SELECT TOP 1 @Val = Seed
FROM tblsRefSeed WITH (NOLOCK)

IF @Val <= 9998
-- The value is less than 9998 increment by one
BEGIN
    Update tblsRefSeed WITH (UPDLOCK)
    SET Seed = Seed + 1
END
IF @Val >= 9999
-- The value is at the maximum value set to 1
BEGIN
    Update tblsRefSeed WITH (UPDLOCK)
    SET Seed = 1
END

SELECT TOP 1 Seed
FROM tblsRefSeed WITH (NOLOCK)

GO

Any help will be greatly appreciated.


Larry Asher
__________________
Larry Asher
Reply With Quote
  #2 (permalink)  
Old March 16th, 2004, 05:55 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: , , United Kingdom.
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Hi Larry,

Its a common problem with updates, what's happening is that the recordset you get back has no fields, just the "1 row affected" message from the update statement.

Either add Set rs = rs.NextRecordset before you try the read, or just add SET NOCOUNT ON to your stored proc.

BTW your locking hints look a bit odd (presumably coz you've tried all sorts of options to get it working?). Don't you just need an UPDLOCK on the first select statement?

hth
Phil
Reply With Quote
  #3 (permalink)  
Old March 16th, 2004, 08:46 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: McPherson, Kansas, USA.
Posts: 128
Thanks: 0
Thanked 0 Times in 0 Posts
Default

In regards to rs.NextRecordset the SPROC should be returning a recordset containing one column/field, in this case it is the Seed field. The last statement in the SPROC is a SELECT statement which should make this a row returning call.

In regards to the locking hints each statement, SELECT or UPDATE, executes individually so the locking hints are in effect only while the statement is being executed. In addition you cannot use an UPDLOCK in a SELECT statement. I also think that locking hints need to be thought out carefully especially the NOLOCK.

The part that has me most confused here is things are not working as they have been (years) and I cannot seem to find the answers I am looking for. So, I find myself having to create some work arounds that I am not happy with. One because I do not think they are as good of a solution and secondly because I am not exactly sure why things are working as they did.

When I say not working as they did let me explain. In the past I used a dll to manage calls to the database. I changed this to an ActiveX exe so that I could share the connection object. Now when I try to set the active connection property of the command object I get an error saying it is of the wrong type, wrong arguments, wrong params, etc. This happened once when I was recently revising the dll as well. However, when this happened in the dll it was resolved, after all else failed and I re-booted my machine. No such luck with the ActiveX exe. However, all of the other database calls/functions work properly. Except I am left without any means to call a row returning SPROC.

If I make the connection object local I can set the active connection property of the command object, but still unable to return the rows from the SPROC. What I am getting in return is a closed recordset object?††

This is a bit more wordy than I would like and probably lacking some details which I would be happy to provide if anyone thinks it may help.

Once again any help will be very much appreciated.

Larry Asher
Reply With Quote
  #4 (permalink)  
Old March 16th, 2004, 10:00 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: , , United Kingdom.
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Quote:
quote:
In regards to rs.NextRecordset the SPROC should be returning a recordset containing one column/field, in this case it is the Seed field. The last statement in the SPROC is a SELECT statement which should make this a row returning call.
Larry, just because you have only one select statement that doesn't mean you only get one recordset! I assume you're using the SQLOLEDB driver? With this driver each SQL statement within a stored procedure returns a "result", either a count of rows affected, or a resultset. In the case of your stored proc you are getting back 2 recordsets: the 1st is the count of rows affected by the UPDATE statement and the 2nd is the resultset from the SELECT statement. That is why you are seeing the 'closed recordset' error.

Quote:
quote:
In regards to the locking hints each statement, SELECT or UPDATE, executes individually so the locking hints are in effect only while the statement is being executed.
Yes you're right. personally I would put the whole thing in a TRANS and issue and UPDLOCK only against the SELECT statement - but it's up to you of course.

Quote:
quote:
In addition you cannot use an UPDLOCK in a SELECT statement.
Nonsense. I quote from BOL
"Use update locks instead of shared locks while reading a table, and hold locks until the end of the statement or transaction. UPDLOCK has the advantage of allowing you to read data (without blocking other readers) and update it later with the assurance that the data has not changed since you last read it. "

rgds
Phil
Reply With Quote
  #5 (permalink)  
Old March 16th, 2004, 10:12 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: McPherson, Kansas, USA.
Posts: 128
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Returning more than one recordset was something I was not aware of. I could write my SPROC to address that. Also, I do stand corrected in regards to the UPLOCK as well. I had misunderstood the BOL definition of NOLOCK.

"Do not issue shared locks and do not honor exclusive locks. When this option is in effect, it is possible to read an uncommitted transaction or a set of pages that are rolled back in the middle of a read. Dirty reads are possible. Only applies to the SELECT statement."

So, thank you very much.

Do you have any ideas as to why the command object would not allow me to set the active connection property?

Here is the essence of what is happening. I have an ActiveX exe that accepts a connection object as a parameter by reference. When I try to set the command objects active connection property an error is raise arguments of wrong type, wrong parameters, etc.

To Phil I am much obliged, thanks.


Larry Asher
Reply With Quote
  #6 (permalink)  
Old March 16th, 2004, 10:33 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: , , United Kingdom.
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Quote:
quote:
Do you have any ideas as to why the command object would not allow me to set the active connection property?

Here is the essence of what is happening. I have an ActiveX exe that accepts a connection object as a parameter by reference. When I try to set the command objects active connection property an error is raise arguments of wrong type, wrong parameters, etc.
Larry, I think its a COM/ADO problem. You say you used to have it in a DLL but you changed it to an EXE? Well you know that DLLs run in-process and EXEs run out-of-process right? So in COM terms what you are trying to do now is marshall the Connection object across a process boundary, but you're getting problems because ADO doesn't know how to marshall Connections, Commands etc across process boundaries. I think you'll have to either revert back to a DLL, or change your EXE to accept the connection string and re-create the connection (not as bad as it sounds because with ADO's connection pooling you'll just get the same connection object back out of the pool without the overhead of re-creating it).

hth
Phil
Reply With Quote
  #7 (permalink)  
Old March 16th, 2004, 11:10 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: McPherson, Kansas, USA.
Posts: 128
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Phil,

I was think the problem was related to out of process versus in process.

I am going to have to do some reading on connection pooling then. That is what I was trying to accomplish with the COM Server. I am trying to avoid a problem I ran into last year, not really a problem but I didn't like it. I have several dlls that access the database, such as, a security dll and other that provide specific functionality. In the end when I went it looked back at the SQL Enterprise Manager each user had about three connection to the database (each dll) - not what I wanted. The problem arises with encapsulation so I thought I could use the ActiveX exe to manage connections to the database if the client requested a global connection then if the named connection exist it set the connection equal to that connection object, otherwise a new one is created.

I think you understand what I am trying to do and perhaps I have gone about it the wrong way.

Once again thank you very much.

Larry Asher
Reply With Quote
  #8 (permalink)  
Old March 25th, 2004, 06:49 PM
RB RB is offline
Registered User
 
Join Date: Mar 2004
Location: Edmonton, Alberta, Canada.
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I've known about this for awhile but don't know why Microsoft choose to put this behavior in with the SQLOLEDB driver?

What is the purpose of sending the update rowcount back as the first recordset? Can it actually be used? I have not been able to actually read this.

Do you have a code snippet where this might be a useful feature?

Thanks in advance for your comments.

RB
Reply With Quote
  #9 (permalink)  
Old March 25th, 2004, 06:58 PM
Friend of Wrox
 
Join Date: Jun 2003
Location: McPherson, Kansas, USA.
Posts: 128
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I don't know of any useful purpose because like yourself I have been unable to read multiple recordsets - it is not supported. So therefore it requires to calls to the database instead of just one.

You've got me?

Larry Asher
Reply With Quote
  #10 (permalink)  
Old March 25th, 2004, 08:31 PM
RB RB is offline
Registered User
 
Join Date: Mar 2004
Location: Edmonton, Alberta, Canada.
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by xgbnow
 I don't know of any useful purpose because like yourself I have been unable to read multiple recordsets - it is not supported. So therefore it requires to calls to the database instead of just one.

You've got me?

Larry Asher

I can read multiple recordsets just fine but not the one the uses up space for the "number of rows" returned.

Try this:

1. Create a proc that does an insert
2. Select the identity value (alias it if you want it to have a field name)
3. Do another select (Select * from sometable)
4. See which ones you can read / access from VB Code (I'm doing it in VB6)

I can not read/use/open up the first recordset returned from the insert statement which would be the number of rows.

I can using the following code "set rs = rs.nextrecordset" access the identity value generated by sql.

I can then use "set rs=rs.nextrecordset" to access and work with all the records selected using the Select * statement.


My question is more of an architecture "why" would Microsoft ship the insert statement's "rows affected" back when it is in a recordset that can't be accessed. (At least I don't know how to.)

RB




Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Stored Proc that returns a value elygp SQL Server 2000 4 May 9th, 2007 02:05 AM
Calling an insert stored proc from a select stored dzitam SQL Language 10 April 2nd, 2007 01:39 PM
How are Carriage Returns stored? SQLScott SQL Server 2005 2 December 1st, 2006 04:07 PM
How are Carriage Returns stored? SQLScott SQL Server 2000 3 November 24th, 2006 10:37 AM
add new record to ADO recordset via stored proc tbullard Access 0 January 20th, 2006 02:35 PM



All times are GMT -4. The time now is 02:38 PM.


Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.