X Tutup
// created on 17/11/2002 at 19:04 // Npgsql.NpgsqlTransaction.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph and the following two paragraphs appear in all copies. // // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. using System; using System.Data; using System.Data.Common; using System.Reflection; using System.Resources; using System.Text; using System.Threading; using Common.Logging; using Npgsql.Localization; namespace Npgsql { /// /// Represents a transaction to be made in a PostgreSQL database. This class cannot be inherited. /// public sealed class NpgsqlTransaction : DbTransaction { private NpgsqlConnection _conn = null; private readonly IsolationLevel _isolation = IsolationLevel.ReadCommitted; private bool _disposed = false; static readonly ILog _log = LogManager.GetCurrentClassLogger(); internal NpgsqlTransaction(NpgsqlConnection conn) : this(conn, IsolationLevel.ReadCommitted) { } internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation) { _conn = conn; _isolation = isolation; if (isolation == IsolationLevel.RepeatableRead) { conn.Connector.ExecuteBlind(QueryManager.BeginTransRepeatableRead); } else if ((isolation == IsolationLevel.Serializable) || (isolation == IsolationLevel.Snapshot)) { conn.Connector.ExecuteBlind(QueryManager.BeginTransSerializable); } else { // Set isolation level default to read committed. _isolation = IsolationLevel.ReadCommitted; conn.Connector.ExecuteBlind(QueryManager.BeginTransReadCommitted); } _conn.Connector.Transaction = this; } /// /// Gets the NpgsqlConnection /// object associated with the transaction, or a null reference if the /// transaction is no longer valid. /// /// The NpgsqlConnection /// object associated with the transaction. public new NpgsqlConnection Connection { get { return _conn; } } /// /// DB connection. /// protected override DbConnection DbConnection { get { return Connection; } } /// /// Specifies the IsolationLevel for this transaction. /// /// The IsolationLevel for this transaction. /// The default is ReadCommitted. public override IsolationLevel IsolationLevel { get { if (_conn == null) { throw new InvalidOperationException(L10N.NoTransaction); } return _isolation; } } /// /// Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && this._conn != null) { if (_conn.Connector.Transaction != null) { if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) != 0) { // can't count on Rollback working if the thread has been aborted // need to copy since Cancel will set it to null NpgsqlConnection conn = _conn; Cancel(); // must close connection since transaction hasn't been rolled back conn.Close(); } else { this.Rollback(); } } this._disposed = true; } base.Dispose(disposing); } /// /// Commits the database transaction. /// public override void Commit() { _log.Debug("Commit transaction"); CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(L10N.NoTransaction); } _conn.Connector.ExecuteBlind(QueryManager.CommitTransaction); _conn.Connector.Transaction = null; _conn = null; } /// /// Rolls back a transaction from a pending state. /// public override void Rollback() { _log.Debug("Rollback transaction"); CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(L10N.NoTransaction); } _conn.Connector.ExecuteBlindSuppressTimeout(QueryManager.RollbackTransaction); _conn.Connector.Transaction = null; _conn = null; } /// /// Rolls back a transaction from a pending savepoint state. /// public void Rollback(String savePointName) { CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(L10N.NoTransaction); } if (!_conn.Connector.SupportsSavepoint) { throw new InvalidOperationException(L10N.SavePointNotSupported); } if (savePointName.Contains(";")) { throw new InvalidOperationException(L10N.SavePointWithSemicolon); } _conn.Connector.ExecuteBlindSuppressTimeout(string.Format("ROLLBACK TO SAVEPOINT {0}", savePointName)); } /// /// Creates a transaction save point. /// public void Save(String savePointName) { CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(L10N.NoTransaction); } if (!_conn.Connector.SupportsSavepoint) { throw new InvalidOperationException(L10N.SavePointNotSupported); } if (savePointName.Contains(";")) { throw new InvalidOperationException(L10N.SavePointWithSemicolon); } _conn.Connector.ExecuteBlind(string.Format("SAVEPOINT {0}", savePointName)); } /// /// Cancel the transaction without telling the backend about it. This is /// used to make the transaction go away when closing a connection. /// internal void Cancel() { CheckDisposed(); if (_conn != null) { _conn.Connector.Transaction = null; _conn = null; } } internal bool Disposed { get { return _disposed; } } internal void CheckDisposed() { if (_disposed) { throw new ObjectDisposedException(typeof(NpgsqlTransaction).Name); } } } }
X Tutup