e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
157 lines
4.7 KiB
C#
157 lines
4.7 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="LocalTransaction.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
#region Using directives
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Transactions;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.Threading;
|
|
|
|
#endregion
|
|
|
|
namespace System.Workflow.Runtime.Hosting
|
|
{
|
|
/// <summary>
|
|
/// This class wraps a local transaction (DbTransaction) by implementing IPromotableSinglePhaseNotification:
|
|
/// It instantiate a DbTransaction and never allows promotion to a DTC transaction.
|
|
/// </summary>
|
|
internal sealed class LocalTransaction : IPromotableSinglePhaseNotification
|
|
{
|
|
readonly DbTransaction transaction;
|
|
System.Data.Common.DbConnection connection;
|
|
ManualResetEvent handle;
|
|
object syncRoot = new Object();
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Wraps a local transaction inside
|
|
/// </summary>
|
|
/// <param name="dbHelper"></param>
|
|
internal LocalTransaction(DbResourceAllocator dbHelper, ManualResetEvent handle)
|
|
{
|
|
if (null == handle)
|
|
throw new ArgumentNullException("handle");
|
|
|
|
// Open a connection that specifically does not auto-enlist ("Enlist=false" in connection string)
|
|
// to prevent auto-promotion of the transaction
|
|
this.connection = dbHelper.OpenNewConnectionNoEnlist();
|
|
this.transaction = this.connection.BeginTransaction();
|
|
this.handle = handle;
|
|
}
|
|
|
|
#endregion Constructor
|
|
|
|
|
|
#region Accessors
|
|
|
|
public System.Data.Common.DbConnection Connection
|
|
{
|
|
get { return this.connection; }
|
|
}
|
|
|
|
public DbTransaction Transaction
|
|
{
|
|
get { return this.transaction; }
|
|
}
|
|
|
|
#endregion Accessors
|
|
|
|
|
|
#region IPromotableSinglePhaseNotification Members
|
|
|
|
public void Initialize()
|
|
{
|
|
}
|
|
|
|
public void SinglePhaseCommit(SinglePhaseEnlistment en)
|
|
{
|
|
if (en == null)
|
|
throw new ArgumentNullException("en");
|
|
|
|
//
|
|
// Wait until IPendingWork members have completed (WinOE bugs 17580 and 13395)
|
|
try
|
|
{
|
|
handle.WaitOne();
|
|
}
|
|
catch (ObjectDisposedException)
|
|
{
|
|
// If an ObjectDisposedException is thrown because
|
|
// the WaitHandle has already closed, nothing to worry
|
|
// about. Move on.
|
|
}
|
|
|
|
lock (syncRoot)
|
|
{
|
|
try
|
|
{
|
|
this.transaction.Commit();
|
|
en.Committed();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
en.Aborted(e);
|
|
}
|
|
finally
|
|
{
|
|
if ((null != connection) && (ConnectionState.Closed != connection.State))
|
|
{
|
|
connection.Close();
|
|
connection = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Rollback(SinglePhaseEnlistment en)
|
|
{
|
|
if (en == null)
|
|
throw new ArgumentNullException("en");
|
|
|
|
//
|
|
// Wait until IPendingWork members have completed (WinOE bugs 17580 and 13395)
|
|
try
|
|
{
|
|
handle.WaitOne();
|
|
}
|
|
catch (ObjectDisposedException)
|
|
{
|
|
// If an ObjectDisposedException is thrown because
|
|
// the WaitHandle has already closed, nothing to worry
|
|
// about. Move on.
|
|
}
|
|
// DbTransaction.Dispose will call Rollback if the DbTransaction is not Zombied.
|
|
// Not safe to call DbTransaction.Rollback here as the the underlining
|
|
// DbTransaction may have already been Rolled back
|
|
lock (syncRoot)
|
|
{
|
|
if (null != transaction)
|
|
transaction.Dispose();
|
|
|
|
if ((null != connection) && (ConnectionState.Closed != connection.State))
|
|
{
|
|
connection.Close();
|
|
connection = null;
|
|
}
|
|
|
|
en.Aborted();
|
|
}
|
|
}
|
|
|
|
public byte[] Promote()
|
|
{
|
|
throw new TransactionPromotionException(
|
|
ExecutionStringManager.PromotionNotSupported);
|
|
}
|
|
|
|
#endregion IPromotableSinglePhaseNotification Members
|
|
}
|
|
}
|