2011-01-19 5 views
3

C#では、DBを更新するOracleConnectionと、DBを更新するためにC#が呼び出すレガシーVB6 DLL(DLL内ではADODB.Connectionオブジェクトを使用)への参照があります。1つのトランザクション内でDBを更新する管理コードとunamangedコードはありますか?

大規模なトランザクションで両方をラップする必要があるため、管理対象と非管理対象の両方の更新プログラムがロールバックまたはコミットされます。

C#クラスをSystem.EnterpriseServices.ServicedComponentから継承し、[Transaction(TransactionOption.Required)]で装飾してから、最終的にヒットする呼び出しシーケンスを開始するメソッドで[オートコンプリート]を使用してみました。 OracleConnectionおよびVB6 DLLの起動。このよう

:私は私のクラスがパブリック、コンクリートである、と持っていることを確認した

{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) 

:私のテストハーネスがMyClassTxをインスタンス化しようとしたとき

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(); 
     } 
    } 
} 

しかし、私はこのエラーを取得しますパラメータのないコンストラクタ。それでも、インスタンス化されません。

私のアセンブリを強くタイプし、それをCOM +パッケージに入れてからデバッグすることもできますか?私は、VS2010を使用して、ServicedComponentを継承するコードにステップインしていると仮定しました。

私は、COM +を使用しているので、約8年ぶり、そしてこれはC#で動作するように取得しようとしている私は初めてなので、任意の助けをいただければ幸いです!私はここに愚かな道を見出していますし、同じトランザクションに私の管理とunamanagedコードを取得する簡単な方法があるかどう

また

、私を啓発してください!

Googleで何時間も手伝ってくれていません。

多くの感謝!

答えて

3

さて、私はこれで大きな進歩を遂げたと思います。総会はのComVisibleとして設定する必要がありました

  1. :私はこのすべての作業をするために行うために必要な

    追加の手順を実行します。

  2. 私は[assembly:System.EnterpriseServices.ApplicationName( "blahblah")]の値を設定しなければなりません... blahblahはCOM +パッケージの名前になります。
  3. アセンブリには厳密な名前を付け、regsvcs.exeを使用してCOM +に登録する必要がありました。ライブラリのアクティベーションを使用するように設定されていますが、必要であれば完全にはわかりません。私はそれをサーバーのアクティベーションとして試しましたが、それを呼び出すコードがある種のCOM例外をスローしました。
  4. は、次のようなContextUtil.Transaction(トランザクションとしてそれをキャスト)を渡し、OracleConnection.EnlistDistributedTransactionを呼び出す必要があります:

    connection.EnlistDistributedTransaction((ITransaction)ContextUtil.Transaction)。

この後、アセンブリはコンポーネントサービスウィンドウのCOM +アプリケーション一覧に表示されていました。わーい!

VS2010でデバッグしたとき、DoStuffTransactionallyメソッドに入ったときに、新しいトランザクションがコンポーネントサービスエクスプローラでアクティブになりました。

これで、デバッグができるようになりました。

しかし、実際にマネージコードだけでなく、レガシーVB6コードをDoStuffTransactionally内で深く呼び出すためには、レガシーVB6 COMオブジェクトをマネージコードが入っているCOM +アプリケーションに追加する必要がありました。このVB6コードはOracleを呼び出すため、VB6コードでDistribTX = 1およびPROMOTABLE TRANSACTION = PROMOTABLEを設定するために使用していた接続文字列を変更する必要がありました。その後、コードでは、管理された&のアンマネージDB変更を1つのトランザクションとしてコミットしてロールバックしていました。

Yay!

デバッグセッションの最後にエラーが表示されますが、これは意味をなさないものです。うまくいけば、それはデバッグにのみ影響し、リリースコードには影響しません。エラーは次のとおりです。

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. 

これはいつか誰かに役立つことを願っています。

関連する問題