2009-05-01 16 views
1

私がここに開始しました:Implementing LINQ-to-SQL transactions through WCF- パートII

を、私は次のように来ているので。私はレガシーにbasicHttpBindingを使用していますが、私のWCFクライアントはアンマネージドC++(gSOAP)です。だから私はASP.NETセッションを使用して、WCFでaspNetCompatibilityModeを有効にしています。これがうまくいくので、セッションを適切に処理できるようになりました。

私の考えは、セッションごとに別々のLINQ-to-SQL DataContextを割り当て、その方法でトランザクション動作を実現することでした。私がしたいのは、Session内にDataContextインスタンスを格納し、SubmitChanges()を呼び出さずにすべての挿入を行い、次にSubmitChanges()を呼び出してトランザクションをコミットすることです。

残念ながら、SubmitChanges()を呼び出す前にDataContextから以前に挿入したデータをフェッチできないようなLINQ-to-SQLのバグがあります(hereを参照してください)。ドキュメントとヘッダ私は入札自体を取得する必要があります。これはうまくいきません(コードを完全にリファクタリングせずにLINQ-to-SQLの美しさの大部分を失うことなく)...

これで問題は次のようになります:WCFを使ってDataContext単位のトランザクションを正しく実装する方法?クライアントが管理されていないため、私はクライアントからTransactionScopeを伝えることができません。上記のバグのため、内部LINQ-to-SQLトランザクションを使用することはできません。私が持っている唯一のものはASP.NETセッション(これは動作します)です。おそらく私はSessionScopeを何とかSessionに保存できますか?

答えて

1

「トランザクション」と「セッション」は同じ文章で始まると自動的に心配します。

  • それはあなたが解決できないデッドロックの可能性の
  • 多くを外部クライアントに依存して阻止している意味:私の意見と経験で、それは単に、複数のWCFは、単一の作業トランザクションの単位を求めて検討してスケールしません - つまりのみタイムアウト、むしろ検出することができデシベル中心のデッドロックよりも
  • あなたはスティッキーロードバランシング

個人的に使用するように強制されている

  • 、私は、単一の作業単位で作業しようとすることができます。つまり、クライアントがのパッケージをの完全なパッケージにしてアトミックな操作として送信するか、セッションを介して別々に行うことを意味する可能性があります。つまり、複数の呼び出しに対して何をバッファするかあなたが必要なものすべてを持っているとき。

    どちらの場合でも、結果として、単一の実装で作業単位が動作し、db-transactionsまたはambient(TransactionScope)トランザクションが正常に動作するようになります。 (あなたのシナリオでは)周囲トランザクションの利点は、それが複数のデータコンテキストにわたって機能することですが、あまり頭痛のないようにSingleコールを(関連する質問に従って)修正することが可能であることが期待されます。

    または、問題が解決したことを確認した.NET 4.0までお待ちください。さて、最後はおそらく短期的には役に立たないでしょう...

  • +0

    ありがとうございました。まあ、Single()呼び出しを修正するのは問題があります。なぜなら、from ... where ... ... LINQ構文を使用することができないからです。そして、これはLINQをあまりエキサイティングにします=) –

    +0

    LINQがリポジトリレベルでどのようにWCF境界と無関係でなければならないのかわかりません...少なくとも、IMO。 –

    0

    重要なことは、同じ接続とトランザクションを再利用することです。私は、既存の接続をとるDataContextでコンストラクタを使用します。セッションが開始したら、接続とトランザクションを割り当ててトランザクションを開始します。接続とトランザクションの両方をセッションに格納します。次に、各呼び出しで、同じ接続とトランザクションを使用してDataContextを再作成します。完了したら、トランザクションをコミットするメソッドを呼び出します。セッションのタイムアウトが発生したら、トランザクションをロールバックする必要があります。

    public bool CreateTransaction() 
    { 
        var connection = new SqlConnection(connectionString); 
        var transaction = connection.BeginTransaction(); 
        Session["DBConnection"] = connection; 
        Session["DBTransaction"] = transaction; 
    
        return true; 
    } 
    
    private DBDataContext CreateContextFromSession() 
    { 
         if (Session["DBConnection"] == null) 
          throw new NullReferenceException("No connection available for transaction."); 
         if (Session["DBTransaction"] == null) 
          throw new NullReferenceException("No transaction available."); 
    
         var context = new DBDataContext((IDbConnection)Session["DBConnection"]); 
         context.Transaction = (DbTransaction)Session["DBTransaction"]; 
    
         return context; 
    } 
    
    public Tender CreateTender(...) 
    { 
        var context = CreateContextFromSession(); 
    
        var tender = new Tender { ... }; 
        context.Tenders.InsertOnSubmit(tender); 
        context.SubmitChanges(); 
    
        return tender; 
    } 
    
    public void CommitTransaction() 
    { 
        var transaction = (DbTransaction)Session["DBTransaction"]; 
        transaction.Commit(); 
        Session.Remove("DBTransaction"); 
    
        var connection = (IDbConnection)Session["DBConnection"]; 
        connection.Close(); 
        Session.Remove("DBConnection"); 
    } 
    
    関連する問題