我的任务是将遗留的 VB6 应用程序(使用 MS Access 作为数据库,不要问)增量移植到 .NET。
这将是一个很长的文章,但我认为最好提供一些背景信息。
此应用程序有一个带有菜单的主 MDI 表单,该菜单是根据应用程序文件夹中的 DLL 动态创建的。它本质上是一种插件:每个 DLL 都由一个菜单项表示,当单击该菜单项时,将打开 DLL 中包含的主窗体,并SetParent()
根据需要进行调用。
MDI 表格是我的起点。我想重写足够多的内容(当然,我要进行重新设计和单元测试)以便能够打开所述表单。一旦我确定了那个,我将开始一次重写一个 DLL。
每个 DLL 都需要一个 ADO 连接,我已经能够从 C# 传递它。
问题是,其中一个插件(至少,但可能还有许多其他插件)使用 ADOX 在数据库上做事,问题就在这里:当我尝试将 ADOX.Catalog 的 ActiveConnection 属性设置为 ADO 连接时,所有我得到的是运行时错误 3001:Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
我一生都无法弄清楚我做错了什么。
VB6 代码尽可能简单:
Dim c As New ADOX.Catalog
Set c.ActiveConnection = theAdoConnectionComingFromDotNet ' error!
创建 ADO 连接的 C# 代码与 VB 代码一样简单:
var conn = new ADODB.Connection();
conn.Open("Provider=Microsoft.JET.Oledb;[...]");
并且调用Open()
成功。如果我尝试ActiveConnection
在 C# 端设置 ,如下所示:
var catalog = new ADOX.Catalog();
catalog.ActiveConnection = conn;
一切正常。
现在,我可以通过简单地在 C# 端实例化 ADOX 并将其传递给 VB6 来解决这个问题,但是调整 VB6 代码(当然没有单个单元测试)可以证明是一个 PITA,我不是甚至确保一开始这很容易(因为该应用程序可以一次使用多个 Access DB,并根据需要打开和关闭与每个数据库的连接)。
那么,有人知道我做错了什么吗?在 C# 中,我尝试从 .NET 选项卡和 COM 选项卡中引用 ADODB(我从 COM 选项卡中选择的 ADO 版本是正确的:2.5...再次,不要问),但仍然没有喜悦。
编辑
当我尝试将 RecordSet 的 ActiveConnection 属性分配给来自 C# 的连接时,会发生完全相同的事情,如下所示:
Dim rs As New ADODB.Recordset
Set rs.ActiveConnection = theAdoConnectionComingFromDotNet
由于 ActiveConnection 是一个变体,我能想到的另一个解决方法是将其设置为连接的 ConnectionString 属性。这行得通,但它每次都会创建并打开一个新连接,坦率地说我不喜欢它。