1

大規模なアプリケーションで Nhibernate と TransactionScope を使用しています。アプリケーションは、3 つのデータベースを変更し、それらの間で分散トランザクションをサポートすることになっています。これは、分散トランザクション内のデータベースで SQL をクエリまたは実行するたびに呼び出すコードです。

IDbConnection connection = new SqlConnection(connectionString);
connection.Open();
 ISession session = SessionFactory.OpenSession(connection);

そして、これは必要な操作が実行された後に呼び出されるコードです

IDbConnection sqlConnection = session.Connection;
if (sqlConnection != null && sqlConnection.State == ConnectionState.Open)
   sqlConnection.Close();
session.Dispose();

update-insert-delete ステートメントを実行すると、コードも次のようにラップされます。

using (var transaction = session.BeginTransaction())
{  //code here

transaction.Commit();}

これはかなり標準的なものだと思います。今...私はこのusingブロック内でこれらの操作を行います:

using (TransactionScope scope = new TransactionScope())
{
//code here
scope.Complete();
}

私の問題は、トランザクションが開始されてから約 6 秒後に散発的に中止されることです (Transaction.Current.TransactionInformation.Status が Aborted になります)。

これは私の分散トランザクション コーディネーターからのトレースです。

pid=6296       ;tid=13300      ;time=04/17/2012-19:34:29.430   ;seq=1          ;eventid=TRANSACTION_MANAGER_STARTED_2            ;;"TM Identifier='(null)                                            '" ;"MS DTC started with the following settings: Security Configuration (OFF = 0 and ON = 1): Network Administration of Transactions = 0, Network Clients = 1, Inbound Transactions = 1, Outbound Transactions = 1, Transaction Internet Protocol (TIP) = 0, XA Transactions = 0, MSDTC RPC Security = Mutual Authentication Required, Account = NT AUTHORITY\NetworkService, Firewall Exclusion = 0, Transaction Bridge Installed = 0, Filtering duplicate events = 1."
pid=6296       ;tid=13300      ;time=04/17/2012-19:34:29.430   ;seq=2          ;eventid=TRACE_SETTINGS                           ;;"TM Identifier='(null)                                            '" ;"Trace Configuration (OFF = 0 and ON = 1): Tracing Of DTC = 1, Tracing Of Transactions = 1, Tracing Of Aborted Transactions = 1, Tracing Of Long-Lived Transactions = 1, Tracing Of All Transactions = 0, Max Limit on Memory Buffers = 0."
pid=6296       ;tid=11372      ;time=04/17/2012-19:35:19.496   ;seq=3          ;eventid=CHECKPOINTING_STOPPED                    ;;"TM Identifier='(null)                                            '" ;"MSDTC is suspending the checkpointing of transactions due to lack of activity"
pid=6296       ;tid=11372      ;time=04/17/2012-19:35:19.496   ;seq=4          ;eventid=TRACING_STOPPED                          ;;"TM Identifier='(null)                                            '" ;"MSDTC is suspending the tracing of long - lived transactions due to lack of activity"
pid=6296       ;tid=10520      ;time=04/17/2012-19:36:31.191   ;seq=5          ;eventid=TRACING_STARTED                          ;;"TM Identifier='(null)                                            '" ;"MSDTC is resuming the tracing of long - lived transactions"
pid=6296       ;tid=10520      ;time=04/17/2012-19:36:31.212   ;seq=6          ;eventid=TRANSACTION_BEGUN                        ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'user_transaction'"
pid=6296       ;tid=10520      ;time=04/17/2012-19:36:31.212   ;seq=7          ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"resource manager #1001 enlisted as transaction enlistment #1. RM guid = 'b9290b2d-9e1d-43ed-a5f3-e417f9b17906'"
pid=6296       ;tid=8016       ;time=04/17/2012-19:36:36.141   ;seq=8          ;eventid=RECEIVED_ABORT_REQUEST_FROM_BEGINNER     ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"received request to abort the transaction from beginner"
pid=6296       ;tid=8016       ;time=04/17/2012-19:36:36.141   ;seq=9          ;eventid=TRANSACTION_ABORTING                     ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"transaction is aborting"
pid=6296       ;tid=8016       ;time=04/17/2012-19:36:36.141   ;seq=10         ;eventid=RM_ISSUED_ABORT                          ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1001 for transaction enlistment #1"
pid=6296       ;tid=8016       ;time=04/17/2012-19:36:36.219   ;seq=11         ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1001 for transaction enlistment #1"
pid=6296       ;tid=8016       ;time=04/17/2012-19:36:36.219   ;seq=12         ;eventid=TRANSACTION_ABORTED                      ;tx_guid=5c61419a-eec2-49c1-aaa1-007645a72e32     ;"TM Identifier='(null)                                            '" ;"transaction has been aborted"

私が間違っていることと、トランザクションが中止されないようにする方法を知っている人はいますか? 前もって感謝します。

更新 1: transactionscope オブジェクトをインスタンス化した直後に 2 つのデータベースの 2 つのセッションを開くと、上記のエラーが発生します。1 つのデータベースに対してセッションを開き、後で他のデータベースの 1 つに対してセッションを開くと、次のエラーが発生します。

The PROMOTE TRANSACTION request failed because there is no local transaction active.

これは、connection.Open() に到達し、2 番目のデータベースへの接続が開かれているときに発生します。

4

1 に答える 1

1

これが複数のデータベースで役立つかどうかはわかりませんが、そのシナリオでこのコードをテストしていません。これは、トランザクションを処理する方法の例です。

 public interface ISessionManager : IDisposable
{
    ISession Session { get; set; }
    ISession GetSession();
}

public class SessionManager : ISessionManager
{
    private readonly ISessionFactory _sessionFactory;
    private TransactionScope _scope;
    public SessionManager(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    #region ISessionManager Members

    public ISession Session { get; set; }

    public ISession GetSession()
    {
        if (Session == null)
        {
            Session = _sessionFactory.OpenSession();
            if (!CurrentSessionContext.HasBind(_sessionFactory))
            {
                _scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions {IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted});
                Session.BeginTransaction(IsolationLevel.ReadCommitted);
                CurrentSessionContext.Bind(Session);
            }
        }

        Session = _sessionFactory.GetCurrentSession();
        Session.FlushMode = FlushMode.Never;
        return Session;
    }


    public void Dispose()
    {
        if (CurrentSessionContext.HasBind(_sessionFactory))
        {
            CurrentSessionContext.Unbind(_sessionFactory);
        }
        try
        {
            Session.Transaction.Commit();
            _scope.Complete();
            _scope.Dispose();
            Session.Flush();
        }
        catch (Exception)
        {
            Session.Transaction.Rollback();
            throw;
        }
        finally
        {
            Session.Close();
            Session.Dispose();
        }
    }

    #endregion
}
于 2012-04-19T17:31:05.170 に答える