首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在一个事务中更新数据库的托管和未修改的代码?

在一个事务中更新数据库的托管和未修改的代码?
EN

Stack Overflow用户
提问于 2011-01-20 03:56:00
回答 1查看 1.5K关注 0票数 3

在C#中,我有一个更新数据库的OracleConnection,以及一个对遗留VB6 DLL的引用,C#调用该DLL来更新DB (在DLL中,它使用ADODB.Connection对象)。

我需要将它们都包装在一个大事务中,以便托管和非托管更新一起回滚或提交。

我尝试切换C#类,使其继承自System.EnterpriseServices.ServicedComponent并用事务(TransactionOption.Required)进行装饰,然后在启动调用序列的方法上使用AutoComplete,该序列最终会触发OracleConnection和VB6 DLL调用。

如下所示:

代码语言:javascript
复制
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时,我得到了这个错误:

代码语言:javascript
复制
{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#中使用它,所以如果有任何帮助,我将非常感激!

此外,如果我在这里走的是一条愚蠢的道路,并且有一种更容易的方法将我的托管代码和未管理代码放入同一事务中,请告诉我!

花几个小时使用谷歌并没有多大帮助。

非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-21 04:51:57

好的,我想我已经在这方面取得了重大进展。

为了让这一切正常工作,我需要执行的其他步骤如下:

必须将程序集设置为值。我必须设置程序集: System.EnterpriseServices.ApplicationName("blahblah")

  • ComVisible:

  • ...blahblah成为COM+包的名称。

  • 程序集必须是强名称的,并使用regsvcs.exe在COM+中注册。它被设置为使用库激活,但我不完全确定这是否有必要。我试过将它作为服务器激活,但是调用它的代码抛出了某种COM异常。

  • 你必须像这样调用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。在此之后,代码将托管和非托管数据库更改作为单个事务提交和回滚。

耶!

我确实在调试会话结束时抛出了一个错误,这对我来说没有任何意义。希望它只影响调试,而不是发布代码。错误是:

代码语言:javascript
复制
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.

所以,我希望有一天这能帮助到一些人。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4740020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档