Search code examples
c#vb6adocom-interopadox

Can't set ADOX.Catalog.ActiveConnection to ADODB Connection coming from .NET


I've been tasked with the incremental porting of a legacy VB6 app (using MS Access as a database, don't ask) to .NET.

This is going to be a long one, but I think it's better to give a bit of context.

This app has a main MDI form with a menu, which is created dynamically based on the DLLs found in the app's folders. It's fundamentally a plug-in kind of thing: each DLL is represented by a menu item, which when clicked, will open up the main form contained in the DLL, calling SetParent() as needed.

The MDI form is my starting point. I want to rewrite just enough of it (redesigning and unit testing as I go, of course) to be able to open said forms. Once I'll have that one nailed, I will start rewriting one DLL at a time.

Every DLL needs an ADO connection, which I've been able to pass along from C#.

The thing is, one of those plug-ins (at least, but possibly many others) uses ADOX to do things on the database, and here lies the problem: when I try to set ADOX.Catalog's ActiveConnection property to the ADO connection, all I get is run-time error 3001: Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.

I can't for the life of me figure out what I'm doing wrong.

The VB6 code is as simple as it can possibly get:

Dim c As New ADOX.Catalog
Set c.ActiveConnection = theAdoConnectionComingFromDotNet   ' error!

The C# code that creates the ADO connection is as straightforward as the VB one:

var conn = new ADODB.Connection();
conn.Open("Provider=Microsoft.JET.Oledb;[...]");

and the call to Open() succeeds. If I attempt to set the ActiveConnection on the C# side, like so:

var catalog = new ADOX.Catalog();
catalog.ActiveConnection = conn;

everything works.

Now, I could work around the problem by simply instantiating ADOX on the C# side and passing it to VB6, but tweaking the VB6 code (which of course has not a single unit test) could prove to be a PITA, and I'm not even sure that would be easy to do in the first place (because the app can use multiple Access DBs at once, opening and closing connections to each of them as needed).

So, anybody has any idea of what I'm doing wrong? From C# I've tried referencing ADODB from both the .NET tab and from the COM one (and the ADO version I chose from the COM tab is the right one: 2.5... again, don't ask), but still no joy.

EDIT

The exact same thing happens when I try to assign a RecordSet's ActiveConnection property to the connection that comes from C#, like so:

Dim rs As New ADODB.Recordset
Set rs.ActiveConnection = theAdoConnectionComingFromDotNet

Another workaround I can think of, since ActiveConnection is a Variant, would be to set it to the connection's ConnectionString property. That works, but it would create and open a new connection every time, and quite frankly I wouldn't like it.


Solution

  • It seems the wrong way around, but this is so suspiciously similar to a problem I had – where ADO stopped working in a COM object recompiled on a Win7 machine then used on an XP machine – that I think this may be down to the same thing. Namely, the disastrous Windows update that broke MDAC ADO in COM objects (very long thread, expect slow loading). If so, the official fix can be found here.

    If it's not that and you can't find the solution, I think your best course of action is to just use the connection string workaround you mentioned in your edit. It's not ideal but you say you're going to start rewriting the DLLs anyway, so it will only be a temporary arrangement.