Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Transaction Scope fixes |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sourceforge |
Files: | files | file ages | folders |
SHA1: |
7d43f65e6aaaf9ca5f9ff2a14347cc69 |
User & Date: | rmsimpson 2006-10-05 22:35:22.000 |
Context
2006-10-12
| ||
21:34 | 3.3.8 Codemerge check-in: 79005e2d23 user: rmsimpson tags: sourceforge | |
2006-10-05
| ||
22:35 | Transaction Scope fixes check-in: 7d43f65e6a user: rmsimpson tags: sourceforge | |
21:18 | Work in progress check-in: 230b880a4c user: rmsimpson tags: sourceforge | |
Changes
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | ︙ | |||
102 103 104 105 106 107 108 | /// Nesting level of the transactions open on the connection /// </summary> internal int _transactionLevel; #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Whether or not the connection is enlisted in a distrubuted transaction /// </summary> | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | /// Nesting level of the transactions open on the connection /// </summary> internal int _transactionLevel; #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Whether or not the connection is enlisted in a distrubuted transaction /// </summary> internal SQLiteEnlistment _enlistment; #endif /// <summary> /// The base SQLite object to interop with /// </summary> internal SQLiteBase _sql; /// <summary> /// Commands associated with this connection |
︙ | ︙ | |||
455 456 457 458 459 460 461 | { int x = _commandList.Count; for (int n = 0; n < x; n++) { _commandList[n].ClearCommands(); } | > > > > > > > > > > > > > > > > | > > > | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | { int x = _commandList.Count; for (int n = 0; n < x; n++) { _commandList[n].ClearCommands(); } if (_enlistment != null) { // If the connection is enlisted in a transaction scope and the scope is still active, // we cannot truly shut down this connection until the scope has completed. Therefore make a // hidden connection temporarily to hold open the connection until the scope has completed. SQLiteConnection cnn = new SQLiteConnection(); cnn._sql = _sql; cnn._transactionLevel = _transactionLevel; cnn._enlistment = _enlistment; cnn._connectionState = _connectionState; cnn._enlistment._transaction._cnn = cnn; cnn._enlistment._disposeConnection = true; } else { _sql.Close(); } _enlistment = null; _sql = null; } OnStateChange(ConnectionState.Closed); } /// <summary> |
︙ | ︙ | |||
646 647 648 649 650 651 652 | /// </summary> /// <param name="transaction">The distributed transaction to enlist in</param> public override void EnlistTransaction(System.Transactions.Transaction transaction) { if (_transactionLevel > 0 && transaction != null) throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists"); | | < < | | 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | /// </summary> /// <param name="transaction">The distributed transaction to enlist in</param> public override void EnlistTransaction(System.Transactions.Transaction transaction) { if (_transactionLevel > 0 && transaction != null) throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists"); if (_enlistment != null && transaction != _enlistment._scope) throw new ArgumentException("Already enlisted in a transaction"); _enlistment = new SQLiteEnlistment(this, transaction); } #endif /// <summary> /// Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value /// </summary> /// <param name="opts">The Key/Value pair array to look in</param> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteEnlistment.cs.
︙ | ︙ | |||
11 12 13 14 15 16 17 | using System; using System.Data; using System.Data.Common; using System.Transactions; internal class SQLiteEnlistment : IEnlistmentNotification { | | > > | > > > > > | > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | using System; using System.Data; using System.Data.Common; using System.Transactions; internal class SQLiteEnlistment : IEnlistmentNotification { internal SQLiteTransaction _transaction; internal Transaction _scope; internal bool _disposeConnection; internal SQLiteEnlistment(SQLiteConnection cnn, Transaction scope) { _transaction = cnn.BeginTransaction(); _scope = scope; _disposeConnection = false; _scope.EnlistVolatile(this, System.Transactions.EnlistmentOptions.None); } #region IEnlistmentNotification Members public void Commit(Enlistment enlistment) { SQLiteConnection cnn = _transaction.Connection; cnn._enlistment = null; try { _transaction.IsValid(); _transaction.Connection._transactionLevel = 1; _transaction.Commit(); enlistment.Done(); } finally { if (_disposeConnection) cnn.Dispose(); _transaction = null; _scope = null; } } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } |
︙ | ︙ | |||
58 59 60 61 62 63 64 | return; } preparingEnlistment.Prepared(); } public void Rollback(Enlistment enlistment) { | > | > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | return; } preparingEnlistment.Prepared(); } public void Rollback(Enlistment enlistment) { SQLiteConnection cnn = _transaction.Connection; cnn._enlistment = null; try { _transaction.Rollback(); enlistment.Done(); } finally { if (_disposeConnection) cnn.Dispose(); _transaction = null; _scope = null; } } #endregion } } #endif // !PLATFORM_COMPACT_FRAMEWORK |
Changes to test/TestCases.cs.
︙ | ︙ | |||
146 147 148 149 150 151 152 | Console.WriteLine("\r\nTests Finished."); } internal static void TransactionTest(DbConnection cnn) { using (TransactionScope scope = new TransactionScope()) { | | | | | > | | > | | | | > | | | | | | > | > > > > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | Console.WriteLine("\r\nTests Finished."); } internal static void TransactionTest(DbConnection cnn) { using (TransactionScope scope = new TransactionScope()) { using (DbConnection cnn2 = ((ICloneable)cnn).Clone() as DbConnection) { using (DbCommand cmd = cnn2.CreateCommand()) { // Created a table inside the transaction scope cmd.CommandText = "CREATE TABLE VolatileTable (ID INTEGER PRIMARY KEY, MyValue VARCHAR(50))"; cmd.ExecuteNonQuery(); using (DbCommand cmd2 = cnn2.CreateCommand()) { using (cmd2.Transaction = cnn2.BeginTransaction()) { // Inserting a value inside the table, inside a transaction which is inside the transaction scope cmd2.CommandText = "INSERT INTO VolatileTable (ID, MyValue) VALUES(1, 'Hello')"; cmd2.ExecuteNonQuery(); cmd2.Transaction.Commit(); } } } // Connection is disposed before the transactionscope leaves, thereby forcing the connection to stay open } // Exit the transactionscope without committing it, causing a rollback of both the create table and the insert } // Verify that the table does not exist using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "SELECT COUNT(*) FROM VolatileTable"; try { object o = cmd.ExecuteScalar(); throw new InvalidOperationException("Transaction failed! The table exists!"); |
︙ | ︙ |