internal static void ReleaseContext(OperationContext context, bool atomic = false) { // if this is an atomic operation (a subset of the overall operation), handle the release of the subscriber from the operation if(atomic) { if(context.Transaction == null) throw new InvalidOperationException("Cannot call ReleaseContext in an atomic context when there is no attached transaction"); if(context.AtomicOperationCount <= 0) throw new InvalidOperationException("Unexpected error: ReleaseContext was called in an atomic context and there was an attached transaction, but the AtomicOperationCount was " + context.AtomicOperationCount); // decrement the atomic counter to keep track of how many subscribers are still making use of the transaction context.AtomicOperationCount--; // if this was the last subscriber to the transaction, we can finalise the transaction, depending on how the operation went if(context.AtomicOperationCount == 0) { try { if(context.RollbackRequested) context.Transaction.Rollback(); else context.Transaction.Commit(); } catch(Exception ex) { throw new Exception("Unable to finalise the transaction for the current storage operation: " + ex.Message, ex); } context.Transaction = null; } } // decrement the overall operation count for the current context context.OperationCount--; if(context.OperationCount == 0) { if(context.IsConnectionInitialised && context.Connection.State == ConnectionState.Open) context.Connection.Close(); OperationContext temp; _connections.TryRemove(context.Hash, out temp); } }
private static OperationContext AcquireContext(ConnectionSource source, bool atomic, IsolationLevel? isolationLevel = null) { OperationContext context; var hash = source.GetHashForThread(); // get the existing context for the current thread if(!_connections.TryGetValue(Thread.CurrentThread.ManagedThreadId, out context)) { // start a new context context = new OperationContext { Source = source, Hash = hash, }; // try and add the new context (should work every time unless there is some kind of unpredictable race condition in play) if(!_connections.TryAdd(hash, context)) context = _connections[hash]; // this line should never be reached, but if it is and it fails, some rethinking of this code is probably in order... } context.OperationCount++; if(atomic) { if(context.AtomicOperationCount == 0) context.Transaction = isolationLevel.HasValue ? context.Connection.BeginTransaction(isolationLevel.Value) : context.Connection.BeginTransaction(); context.AtomicOperationCount++; } return context; }
public void Release() { if(_disposed) throw new Exception(DisposedExceptionMessage); ConnectionStateManager.ReleaseContext(Context); _disposed = true; Context = null; }