Passing a Recordset from VB6 to VB.Net (QueryInterface failed.)

G

Guest

I am getting an error when trying to use an ADODB.Recordset that was passed
from a VB6 application to a VB.Net class library using COM Interop. I am
running this on WinXP SP2 using the .Net Framework 1.1 and MDAC 2.8 SP1.

This is what I've done:
- I compiled the VB.Net DLL and registered it so it can be used in the VB6
app using "regasm /tlb:VBNETClass.tlb VBNETClass.dll".
- From the VB6 app, I added a reference to the VB.Net DLL.
- I added references to the ADO 2.8 Library from both the VB6 app and the
VB.Net library. (I also tried ADO 2.6 and 2.7 later but they had the same
results.)
- I built the VB6 EXE and copied it to the directory containing the VB.Net
DLL.

When I run the VB6 EXE, all of the message boxes appear fine except for the
one on the last line of PrintRecordCount below. Instead, I get the following
error:

- - - -
Run-time error '-2147467262 (80004002)';
QueryInterface for interface ADODB._Recordset failed.
- - - -
(The debugger shows it to be a System.InvalidCastException.)

Any ideas?


VB6 APP

Private Sub Command1_Click()

Dim ccw As New VBNETClass.Class1

Dim rs As New ADODB.Recordset
Set rs = CreateObject("ADODB.Recordset")
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.Fields.Append "FieldName1", adVarChar, 10
rs.Fields.Append "FieldName2", adInteger
rs.Open

rs.AddNew
rs("FieldName1") = "David"
rs("FieldName2") = 17
rs.Update

rs.Sort = "FieldName2"
rs.MoveFirst

MsgBox ("In VB6 App, about to call VB.Net class...")
' this line works
MsgBox ("In VB6 Class, rs.RecordCount = " & rs.RecordCount)

ccw.PrintRecordCount (rs)

End Sub



VB.NET CLASS LIBRARY (VBNETClass)

Public Class Class1
Public Function PrintRecordCount(ByVal rs As ADODB.Recordset)

MsgBox("In VB.Net Class, about to display RecordCount... ")
' this line produces the error
MsgBox("In VB.Net Class, rs.RecordCount = " & rs.RecordCount)

End Function
End Class

(I also tried changing the type of the input parameter to
ADODB.RecordsetClass and ADODB._Recordset but the same error resulted.)
 
M

Marco Frontini

If you are using the same ADODB versione in both VB6 and VB.NET
applications, remove the line
Set rs = CreateObject("ADODB.Recordset")
from VB6 code.
You already have a valid instance of Recordset from the line
Dim rs As New ADODB.Recordset


Bye.
 
F

Fredrik Wahlgren

Marco Frontini said:
If you are using the same ADODB versione in both VB6 and VB.NET
applications, remove the line
Set rs = CreateObject("ADODB.Recordset")
from VB6 code.
You already have a valid instance of Recordset from the line
Dim rs As New ADODB.Recordset


Bye.
Alternatively, and I think also better, is to do it the other way, i.e.

Dim rs As ADODB.Recordset
Set rs = CreateObject("ADODB.Recordset")

/Fredrik
 
G

Guest

If you cannot get this to work this way maybe you could try:
In VB6, write the contents of the recordset to XML (a string).
Pass the string as an argument instead.
In VB.NET, accept a string, create a recordset object, read the XML into the
recordset.

I've done something similar...
 
G

Guest

I gave that a try but it didn't work. I still get the same error.
Thanks, though, for the suggestion.
 
G

Guest

Thanks for the post. Unfortunately after trying that change, I still get the
same error.
 
F

Fredrik Wahlgren

adam said:
Thanks for the post. Unfortunately after trying that change, I still get the
same error.


:

Why not extract the recordcount into a local variable before printing it? I
think that should work.

/Fredrik
 
M

Marco Frontini

Declare your argument as Object and in the called procedure use an
OleDbDataAdapter to fill a .NET DataTable

Public Function PrintRecordCount(ByVal rs As Object)

Dim dt As DataTable = New DataTable("TableName")
Dim da As System.Data.OleDb.OleDbDataAdapter = new
System.Data.OleDb.OleDbDataAdapter()
da.Fill(dt, rs)

... now use the dt DataTable ....
 
W

William \(Bill\) Vaughn

I would be surprised if this works since the XML extruded by ADO classic is
not the same as the XML expected by ADO.NET.
I would probably read the ADO classic Recordset directly into an ADO.NET
table using the OleDb provider that can Fill from them directly.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
 
F

Fredrik Wahlgren

If all you want is to print the recordcount, why not pass a long rather than
the entire recordset?

/Fredrik
 
G

Guest

This will probably work in DOT NET if you create an instance of the ADODB
Recordset in .NET. Since it is an ADODB Recordset that created the XML it
should be ok and the recordset in .NET should recognize it as appropriately
formatted XML for a "ADODB.Recordset".

The application I use this for actually does it this way:

Client-side VBScript creates an ADODB.Recordset. The open() of the recordset
references an aspx page.

In the aspx page...
-Create an ADODB connection and recordset in the .NET web page
-Read data from SQL into the recordset
-Write the XML output of the recordset to the browser

An Excel document is then created by the client VBScript and the document is
populated by looping through the recordset and adding the data to the Excel
document.
(This way gets around security problems encountered by doing the same thing
using streams.)
 
G

Guest

Marco/Bill, I tried your suggestion of using OleDb to fill a DataTable from
the passed in Recordset but I get this error on the "da.Fill(dt, rs)" line:

- - - -
Run-time error '-2147024809 (80070057)';
Object is not an ADODB.Recordset or an ADODB.Record.
Parameter name: adodb
- - - -

I tried passing in the Recordset as a ADODB.Recordset and as an Object, but
the error came up either way.

I don't quite understand why passing a Recordset from VB6 to VB.Net is so
difficult. Isn't the purpose of COM Interop to make it seamless? Could it
have something to do with my machine's configuration?
 
B

bruce barker

your main problem is vb6 is passing a real com object (adorecoredset). the
..net code is expecting an interop wrapper around a com object. you will need
to write some interop code to do the translation between.

you other option is to build a .net class to implement a recordset, create c
com wrapper, then the vb6 code can call the wrapped .net code to get a
recoreset, and access propeties.

-- bruce (sqlwork.com)




| I am getting an error when trying to use an ADODB.Recordset that was
passed
| from a VB6 application to a VB.Net class library using COM Interop. I am
| running this on WinXP SP2 using the .Net Framework 1.1 and MDAC 2.8 SP1.
|
| This is what I've done:
| - I compiled the VB.Net DLL and registered it so it can be used in the
VB6
| app using "regasm /tlb:VBNETClass.tlb VBNETClass.dll".
| - From the VB6 app, I added a reference to the VB.Net DLL.
| - I added references to the ADO 2.8 Library from both the VB6 app and the
| VB.Net library. (I also tried ADO 2.6 and 2.7 later but they had the same
| results.)
| - I built the VB6 EXE and copied it to the directory containing the
VB.Net
| DLL.
|
| When I run the VB6 EXE, all of the message boxes appear fine except for
the
| one on the last line of PrintRecordCount below. Instead, I get the
following
| error:
|
| - - - -
| Run-time error '-2147467262 (80004002)';
| QueryInterface for interface ADODB._Recordset failed.
| - - - -
| (The debugger shows it to be a System.InvalidCastException.)
|
| Any ideas?
|
|
| VB6 APP
|
| Private Sub Command1_Click()
|
| Dim ccw As New VBNETClass.Class1
|
| Dim rs As New ADODB.Recordset
| Set rs = CreateObject("ADODB.Recordset")
| rs.CursorType = adOpenStatic
| rs.CursorLocation = adUseClient
| rs.Fields.Append "FieldName1", adVarChar, 10
| rs.Fields.Append "FieldName2", adInteger
| rs.Open
|
| rs.AddNew
| rs("FieldName1") = "David"
| rs("FieldName2") = 17
| rs.Update
|
| rs.Sort = "FieldName2"
| rs.MoveFirst
|
| MsgBox ("In VB6 App, about to call VB.Net class...")
| ' this line works
| MsgBox ("In VB6 Class, rs.RecordCount = " & rs.RecordCount)
|
| ccw.PrintRecordCount (rs)
|
| End Sub
|
|
|
| VB.NET CLASS LIBRARY (VBNETClass)
|
| Public Class Class1
| Public Function PrintRecordCount(ByVal rs As ADODB.Recordset)
|
| MsgBox("In VB.Net Class, about to display RecordCount... ")
| ' this line produces the error
| MsgBox("In VB.Net Class, rs.RecordCount = " & rs.RecordCount)
|
| End Function
| End Class
|
| (I also tried changing the type of the input parameter to
| ADODB.RecordsetClass and ADODB._Recordset but the same error resulted.)
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top