在C#中,我有一个更新数据库的OracleConnection,以及对C#调用以更新数据库的旧版VB6 DLL的引用(在DLL中,它使用ADODB.Connection对象)。
我需要将它们包装在一个大事务中,以便托管和非托管更新都回滚或提交。
我尝试切换C#类,使其继承System.EnterpriseServices.ServicedComponent并使用[Transaction(TransactionOption.Required)]进行修饰,然后在启动调用序列的方法上使用[AutoComplete],最终命中OracleConnection和VB6 DLL调用。
像这样:
using System.EnterpriseServices;
{
[Transaction(TransactionOption.Required)]
public class MyClassTx: ServicedComponent
{
private MyClass1 _myClass1;
public MyClassTx()
{
}
// This method automatically commits the transaction if it succeeds.
[AutoComplete]
public void DoStuffTransactionally()
{
// Calls into different objects, doing some work that I'd like to have
// a big transaction around.
_MyClass1 = new MyClass1()
_MyClass1.DoSomeStuff();
}
}
}
但是,当我的测试工具尝试实例化MyClassTx时,我收到此错误:
{System.EnterpriseServices.RegistrationException: Invalid ServicedComponent-derived classes were found in the assembly.
(Classes must be public, concrete, have a public default constructor, and meet all other ComVisibility requirements)
我已经验证我的课程是公开的,具体的,并且有一个无参数的构造函数。不过,它不会实例化。
在我甚至可以调试之前,是否需要强力键入我的程序集并将其放入COM +包中?我会假设,使用VS2010,我可以直接进入ServicedComponent继承代码。
自从我使用COM +以来已经有8年了,这是我第一次尝试将它用于C#,所以任何帮助都将非常感谢!
另外,如果我在这里走一条愚蠢的道路并且有更简单的方法将我的托管和非托管代码放入同一个交易中,请赐教我!
谷歌的几个小时没有多大帮助。
非常感谢!!
答案 0 :(得分:3)
好的,我认为我在这方面取得了重大进展。
我需要采取的其他步骤才能完成所有工作:
你必须调用OracleConnection.EnlistDistributedTransaction,传入ContextUtil.Transaction(将其转换为事务),如下所示:
connection.EnlistDistributedTransaction((ITransaction)ContextUtil.Transaction);
在此之后,程序集显示在“组件服务”窗口的“COM +应用程序”列表中。耶!
更好的是,当我在VS2010中调试时,当我进入DoStuffTransactionally方法时,组件服务资源管理器中的新事务处于活动状态。
所以,让我进行调试。
但是,为了实际获取事务不仅包括托管代码,还包括在DoStuffTransactionally中更深入调用的旧版VB6代码,我需要将旧版VB6 COM对象添加到我的托管代码所在的COM +应用程序中。这个VB6代码正在调用Oracle,我不得不修改VB6代码使用的连接字符串,以使DistribTX = 1和PROMOTABLE TRANSACTION = PROMOTABLE设置。在那之后,代码正在提交并回滚托管&非托管数据库更改为单个事务。
耶!
我在调试会话结束时遇到错误,这对我没有意义。希望它只影响调试而不是发布代码。错误是:
DisconnectedContext was detected
Message: Context 0x4452b0' is disconnected. Releasing the interfaces from the current context (context 0x444fd0). This may cause corruption or data loss. To avoid this problem, please ensure that all contexts/apartments stay alive until the application is completely done with the RuntimeCallableWrappers that represent COM components that live inside them.
所以,我希望有一天能帮助某人。