/******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; /// /// SQLite implementation of DbTransaction. /// public sealed class SQLiteTransaction : DbTransaction { /// /// The connection to which this transaction is bound /// internal SQLiteConnection _cnn; /// /// Constructs the transaction object, binding it to the supplied connection /// /// The connection to open a transaction on /// TRUE to defer the writelock, or FALSE to lock immediately internal SQLiteTransaction(SQLiteConnection connection, bool deferredLock) { _cnn = connection; if (_cnn._transactionLevel++ == 0) { try { using (SQLiteCommand cmd = _cnn.CreateCommand()) { if (!deferredLock) cmd.CommandText = "BEGIN IMMEDIATE"; else cmd.CommandText = "BEGIN"; cmd.ExecuteNonQuery(); } } catch (SQLiteException) { _cnn._transactionLevel--; _cnn = null; throw; } } } /// /// Commits the current transaction. /// public override void Commit() { IsValid(); if (--_cnn._transactionLevel == 0) { try { using (SQLiteCommand cmd = _cnn.CreateCommand()) { cmd.CommandText = "COMMIT"; cmd.ExecuteNonQuery(); } } finally { _cnn = null; } } else { _cnn = null; } } /// /// Returns the underlying connection to which this transaction applies. /// public new SQLiteConnection Connection { get { return _cnn; } } /// /// Forwards to the local Connection property /// protected override DbConnection DbConnection { get { return Connection; } } /// /// Disposes the transaction. If it is currently active, any changes are rolled back. /// protected override void Dispose(bool disposing) { if (_cnn != null) Rollback(); base.Dispose(disposing); } /// /// Gets the isolation level of the transaction. SQLite only supports Serializable transactions. /// public override IsolationLevel IsolationLevel { get { return IsolationLevel.Serializable; } } /// /// Rolls back the active transaction. /// public override void Rollback() { IsValid(); try { using (SQLiteCommand cmd = _cnn.CreateCommand()) { cmd.CommandText = "ROLLBACK"; cmd.ExecuteNonQuery(); } _cnn._transactionLevel = 0; } finally { _cnn = null; } } internal void IsValid() { if (_cnn == null) throw new ArgumentNullException("No connection associated with this transaction"); if (_cnn._transactionLevel == 0) { _cnn = null; throw new SQLiteException((int)SQLiteErrorCode.Misuse, "No transactions active on this connection"); } } } }