internal Transaction(IsolationLevel isoLevel, ISimpleTransactionSuperior superior) { TransactionManager.ValidateIsolationLevel(isoLevel); ArgumentNullException.ThrowIfNull(superior); _isoLevel = isoLevel; // Never create a transaction with an IsolationLevel of Unspecified. if (IsolationLevel.Unspecified == _isoLevel) { _isoLevel = TransactionManager.DefaultIsolationLevel; } _internalTransaction = new InternalTransaction(this, superior); // ISimpleTransactionSuperior is defined to also promote to MSDTC. _internalTransaction.SetPromoterTypeToMSDTC(); _cloneId = 1; }
internal override void EnterState(InternalTransaction tx) { Debug.Assert((tx._promoterType == Guid.Empty) || (tx._promoterType == TransactionInterop.PromoterTypeDtc), "Promoted to MSTC but PromoterType is not TransactionInterop.PromoterTypeDtc"); // The promoterType may not yet be set. This state assumes we are promoting to MSDTC. tx.SetPromoterTypeToMSDTC(); if (tx._outcomeSource._isoLevel == IsolationLevel.Snapshot) { throw TransactionException.CreateInvalidOperationException(TraceSourceType.TraceSourceLtm, SR.CannotPromoteSnapshot, null); } // Set the transaction state CommonEnterState(tx); // Create a transaction with the distributed transaction manager DistributedCommittableTransaction distributedTx = null; try { TimeSpan newTimeout; if (tx.AbsoluteTimeout == long.MaxValue) { // The transaction has no timeout newTimeout = TimeSpan.Zero; } else { newTimeout = TransactionManager.TransactionTable.RecalcTimeout(tx); if (newTimeout <= TimeSpan.Zero) { return; } } // Just create a new transaction. TransactionOptions options = new TransactionOptions(); options.IsolationLevel = tx._outcomeSource._isoLevel; options.Timeout = newTimeout; // Create a new distributed transaction. distributedTx = TransactionManager.DistributedTransactionManager.CreateTransaction(options); distributedTx.SavedLtmPromotedTransaction = tx._outcomeSource; TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.TransactionPromoted(tx.TransactionTraceId, distributedTx.TransactionTraceId); } } catch (TransactionException te) { // There was an exception trying to create the distributed transaction. // Save the exception and let the transaction get aborted by the finally block. tx._innerException = te; TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.ExceptionConsumed(te); } return; } finally { if (distributedTx == null) { // There was an exception trying to create the distributed transaction abort // the local transaction and exit. tx.State.ChangeStateAbortedDuringPromotion(tx); } } // Associate the distributed transaction with the local transaction. tx.PromotedTransaction = distributedTx; // Add a weak reference to the transaction to the promotedTransactionTable. Hashtable promotedTransactionTable = TransactionManager.PromotedTransactionTable; lock (promotedTransactionTable) { // Since we are adding this reference to the table create an object that will clean that // entry up. tx._finalizedObject = new FinalizedObject(tx, distributedTx.Identifier); WeakReference weakRef = new WeakReference(tx._outcomeSource, false); promotedTransactionTable[distributedTx.Identifier] = weakRef; } TransactionManager.FireDistributedTransactionStarted(tx._outcomeSource); // Once we have a promoted transaction promote the enlistments. PromoteEnlistmentsAndOutcome(tx); }
internal Transaction(IsolationLevel isoLevel, ISimpleTransactionSuperior superior) { TransactionManager.ValidateIsolationLevel(isoLevel); if (superior == null) { throw new ArgumentNullException(nameof(superior)); } _isoLevel = isoLevel; // Never create a transaction with an IsolationLevel of Unspecified. if (IsolationLevel.Unspecified == _isoLevel) { _isoLevel = TransactionManager.DefaultIsolationLevel; } _internalTransaction = new InternalTransaction(this, superior); // ISimpleTransactionSuperior is defined to also promote to MSDTC. _internalTransaction.SetPromoterTypeToMSDTC(); _cloneId = 1; }