SQLiteTransaction.cs SQLite事务

来源:互联网 发布:法兰克编程入门 编辑:程序博客网 时间:2024/06/04 23:29


001下载 SQLiteTransaction.cs

/*********************************************************
002 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
003 * Written by Robert Simpson (robert@blackcastlesoft.com)
004 *
005 * Released to the public domain, use at your own risk!
006 ********************************************************/
007 
008namespace Mono.Data.Sqlite
009{
010  using System;
011  using System.Data;
012  using System.Data.Common;
013 
014  /// <summary>
015  /// SQLite implementation of DbTransaction.
016  /// </summary>
017  public sealed class SqliteTransaction : DbTransaction
018  {
019    /// <summary>
020    /// The connection to which this transaction is bound
021    /// </summary>
022    internal SqliteConnection _cnn;
023    internal long _version; // Matches the version of the connection
024    private IsolationLevel _level;
025 
026    /// <summary>
027    /// Constructs the transaction object, binding it to the supplied connection
028    /// </summary>
029    /// <param name="connection">The connection to open a transaction on</param>
030    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>
031    internal SqliteTransaction(SqliteConnection connection, bool deferredLock)
032    {
033      _cnn = connection;
034      _version = _cnn._version;
035 
036      _level = (deferredLock == true) ? IsolationLevel.ReadCommitted : IsolationLevel.Serializable;
037 
038      if (_cnn._transactionLevel++ == 0)
039      {
040        try
041        {
042          using (SqliteCommand cmd = _cnn.CreateCommand())
043          {
044            if (!deferredLock)
045              cmd.CommandText = "BEGIN IMMEDIATE";
046            else
047              cmd.CommandText = "BEGIN";
048 
049            cmd.ExecuteNonQuery();
050          }
051        }
052        catch (SqliteException)
053        {
054          _cnn._transactionLevel--;
055          _cnn = null;
056          throw;
057        }
058      }
059    }
060 
061    /// <summary>
062    /// Commits the current transaction.
063    /// </summary>
064    public override void Commit()
065    {
066      IsValid(true);
067 
068      if (_cnn._transactionLevel - 1 == 0)
069      {
070        using (SqliteCommand cmd = _cnn.CreateCommand())
071        {
072          cmd.CommandText = "COMMIT";
073          cmd.ExecuteNonQuery();
074        }
075      }
076      _cnn._transactionLevel--;
077      _cnn = null;
078    }
079 
080    /// <summary>
081    /// Returns the underlying connection to which this transaction applies.
082    /// </summary>
083    public new SqliteConnection Connection
084    {
085      get return _cnn; }
086    }
087 
088    /// <summary>
089    /// Forwards to the local Connection property
090    /// </summary>
091    protected override DbConnection DbConnection
092    {
093      get return Connection; }
094    }
095 
096    /// <summary>
097    /// Disposes the transaction.  If it is currently active, any changes are rolled back.
098    /// </summary>
099    protected override void Dispose(bool disposing)
100    {
101      if (disposing)
102      {
103        lock (this)
104        {
105          if (IsValid(false))
106            Rollback();
107 
108          _cnn = null;
109        }
110      }
111      base.Dispose(disposing);
112    }
113 
114    /// <summary>
115    /// Gets the isolation level of the transaction.  SQLite only supports Serializable transactions.
116    /// </summary>
117    public override IsolationLevel IsolationLevel
118    {
119      get return _level; }
120    }
121 
122    /// <summary>
123    /// Rolls back the active transaction.
124    /// </summary>
125    public override void Rollback()
126    {
127      IsValid(true);
128 
129      IssueRollback(_cnn);
130 
131      _cnn._transactionLevel = 0;
132      _cnn = null;
133    }
134 
135    internal static void IssueRollback(SqliteConnection cnn)
136    {
137      using (SqliteCommand cmd = cnn.CreateCommand())
138      {
139        cmd.CommandText = "ROLLBACK";
140        cmd.ExecuteNonQuery();
141      }
142    }
143 
144    internal bool IsValid(bool throwError)
145    {
146      if (_cnn == null)
147      {
148        if (throwError == truethrow new ArgumentNullException("No connection associated with this transaction");
149        else return false;
150      }
151 
152      if (_cnn._transactionLevel == 0)
153      {
154        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse, "No transaction is active on this connection");
155        else return false;
156      }
157      if (_cnn._version != _version)
158      {
159        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse, "The connection was closed and re-opened, changes were rolled back");
160        else return false;
161      }
162      if (_cnn.State != ConnectionState.Open)
163      {
164        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse,"Connection was closed");
165        else return false;
166      }
167 
168      return true;
169    }
170  }
171}
001/*********************************************************
002 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
003 * Written by Robert Simpson (robert@blackcastlesoft.com)
004 *
005 * Released to the public domain, use at your own risk!
006 ********************************************************/
007 
008namespace Mono.Data.Sqlite
009{
010  using System;
011  using System.Data;
012  using System.Data.Common;
013 
014  /// <summary>
015  /// SQLite implementation of DbTransaction.
016  /// </summary>
017  public sealed class SqliteTransaction : DbTransaction
018  {
019    /// <summary>
020    /// The connection to which this transaction is bound
021    /// </summary>
022    internal SqliteConnection _cnn;
023    internal long _version; // Matches the version of the connection
024    private IsolationLevel _level;
025 
026    /// <summary>
027    /// Constructs the transaction object, binding it to the supplied connection
028    /// </summary>
029    /// <param name="connection">The connection to open a transaction on</param>
030    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>
031    internal SqliteTransaction(SqliteConnection connection, bool deferredLock)
032    {
033      _cnn = connection;
034      _version = _cnn._version;
035 
036      _level = (deferredLock == true) ? IsolationLevel.ReadCommitted : IsolationLevel.Serializable;
037 
038      if (_cnn._transactionLevel++ == 0)
039      {
040        try
041        {
042          using (SqliteCommand cmd = _cnn.CreateCommand())
043          {
044            if (!deferredLock)
045              cmd.CommandText = "BEGIN IMMEDIATE";
046            else
047              cmd.CommandText = "BEGIN";
048 
049            cmd.ExecuteNonQuery();
050          }
051        }
052        catch (SqliteException)
053        {
054          _cnn._transactionLevel--;
055          _cnn = null;
056          throw;
057        }
058      }
059    }
060 
061    /// <summary>
062    /// Commits the current transaction.
063    /// </summary>
064    public override void Commit()
065    {
066      IsValid(true);
067 
068      if (_cnn._transactionLevel - 1 == 0)
069      {
070        using (SqliteCommand cmd = _cnn.CreateCommand())
071        {
072          cmd.CommandText = "COMMIT";
073          cmd.ExecuteNonQuery();
074        }
075      }
076      _cnn._transactionLevel--;
077      _cnn = null;
078    }
079 
080    /// <summary>
081    /// Returns the underlying connection to which this transaction applies.
082    /// </summary>
083    public new SqliteConnection Connection
084    {
085      get return _cnn; }
086    }
087 
088    /// <summary>
089    /// Forwards to the local Connection property
090    /// </summary>
091    protected override DbConnection DbConnection
092    {
093      get return Connection; }
094    }
095 
096    /// <summary>
097    /// Disposes the transaction.  If it is currently active, any changes are rolled back.
098    /// </summary>
099    protected override void Dispose(bool disposing)
100    {
101      if (disposing)
102      {
103        lock (this)
104        {
105          if (IsValid(false))
106            Rollback();
107 
108          _cnn = null;
109        }
110      }
111      base.Dispose(disposing);
112    }
113 
114    /// <summary>
115    /// Gets the isolation level of the transaction.  SQLite only supports Serializable transactions.
116    /// </summary>
117    public override IsolationLevel IsolationLevel
118    {
119      get return _level; }
120    }
121 
122    /// <summary>
123    /// Rolls back the active transaction.
124    /// </summary>
125    public override void Rollback()
126    {
127      IsValid(true);
128 
129      IssueRollback(_cnn);
130 
131      _cnn._transactionLevel = 0;
132      _cnn = null;
133    }
134 
135    internal static void IssueRollback(SqliteConnection cnn)
136    {
137      using (SqliteCommand cmd = cnn.CreateCommand())
138      {
139        cmd.CommandText = "ROLLBACK";
140        cmd.ExecuteNonQuery();
141      }
142    }
143 
144    internal bool IsValid(bool throwError)
145    {
146      if (_cnn == null)
147      {
148        if (throwError == truethrow new ArgumentNullException("No connection associated with this transaction");
149        else return false;
150      }
151 
152      if (_cnn._transactionLevel == 0)
153      {
154        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse, "No transaction is active on this connection");
155        else return false;
156      }
157      if (_cnn._version != _version)
158      {
159        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse, "The connection was closed and re-opened, changes were rolled back");
160        else return false;
161      }
162      if (_cnn.State != ConnectionState.Open)
163      {
164        if (throwError == truethrow new SqliteException((int)SQLiteErrorCode.Misuse,"Connection was closed");
165        else return false;
166      }
167 
168      return true;
169    }
170  }
171}