2 * Firebird ADO.NET Data provider for .NET and Mono
\r
4 * The contents of this file are subject to the Initial
\r
5 * Developer's Public License Version 1.0 (the "License");
\r
6 * you may not use this file except in compliance with the
\r
7 * License. You may obtain a copy of the License at
\r
8 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
\r
10 * Software distributed under the License is distributed on
\r
11 * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
\r
12 * express or implied. See the License for the specific
\r
13 * language governing rights and limitations under the License.
\r
15 * Copyright (c) 2002, 2005 Carlos Guzman Alvarez
\r
16 * All Rights Reserved.
\r
21 using System.Collections;
\r
23 using FirebirdSql.Data.Common;
\r
25 namespace FirebirdSql.Data.Firebird
\r
27 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/overview/*'/>
\r
28 public sealed class FbTransaction : MarshalByRefObject, IDbTransaction, IDisposable
\r
32 private ITransaction transaction;
\r
33 private FbConnection connection;
\r
34 private IsolationLevel isolationLevel;
\r
35 private bool disposed;
\r
36 private bool isUpdated;
\r
42 IDbConnection IDbTransaction.Connection
\r
44 get { return this.Connection; }
\r
47 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/property[@name="Connection"]/*'/>
\r
48 public FbConnection Connection
\r
52 if (!this.isUpdated)
\r
54 return this.connection;
\r
63 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/property[@name="IsolationLevel"]/*'/>
\r
64 public IsolationLevel IsolationLevel
\r
66 get { return this.isolationLevel; }
\r
71 #region Internal Properties
\r
73 internal ITransaction Transaction
\r
75 get { return this.transaction; }
\r
78 internal bool IsUpdated
\r
80 get { return this.isUpdated; }
\r
85 #region Constructors
\r
87 internal FbTransaction(FbConnection connection) : this(connection, IsolationLevel.ReadCommitted)
\r
91 internal FbTransaction(FbConnection connection, IsolationLevel il)
\r
93 this.isolationLevel = il;
\r
94 this.connection = connection;
\r
101 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbCommandBuilder"]/destructor[@name="Finalize"]/*'/>
\r
104 this.Dispose(false);
\r
109 #region IDisposable Methods
\r
111 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Dispose"]/*'/>
\r
112 public void Dispose()
\r
114 this.Dispose(true);
\r
115 GC.SuppressFinalize(this);
\r
118 private void Dispose(bool disposing)
\r
122 if (!this.disposed)
\r
126 // release any unmanaged resources
\r
127 if (this.transaction != null)
\r
129 if ((this.transaction.State == TransactionState.TransactionStarted
\r
130 || this.transaction.State == TransactionState.TransactionPrepared)
\r
131 && !this.isUpdated)
\r
133 this.transaction.Dispose();
\r
134 this.transaction = null;
\r
138 // release any managed resources
\r
141 this.connection = null;
\r
142 this.transaction = null;
\r
147 this.isUpdated = true;
\r
148 this.disposed = true;
\r
158 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Commit"]/*'/>
\r
159 public void Commit()
\r
163 if (this.isUpdated)
\r
165 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
170 this.transaction.Commit();
\r
171 this.UpdateTransaction();
\r
173 catch (IscException ex)
\r
175 throw new FbException(ex.Message, ex);
\r
180 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Rollback"]/*'/>
\r
181 public void Rollback()
\r
185 if (this.isUpdated)
\r
187 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
192 this.transaction.Rollback();
\r
193 this.UpdateTransaction();
\r
195 catch (IscException ex)
\r
197 throw new FbException(ex.Message, ex);
\r
202 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Save(System.String)"]/*'/>
\r
203 public void Save(string savePointName)
\r
207 if (savePointName == null)
\r
209 throw new ArgumentException("No transaction name was be specified.");
\r
213 if (savePointName.Length == 0)
\r
215 throw new ArgumentException("No transaction name was be specified.");
\r
218 if (this.isUpdated)
\r
220 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
225 FbCommand command = new FbCommand(
\r
226 "SAVEPOINT " + savePointName,
\r
229 command.ExecuteNonQuery();
\r
232 catch (IscException ex)
\r
234 throw new FbException(ex.Message, ex);
\r
239 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Commit(System.String)"]/*'/>
\r
240 public void Commit(string savePointName)
\r
244 if (savePointName == null)
\r
246 throw new ArgumentException("No transaction name was be specified.");
\r
250 if (savePointName.Length == 0)
\r
252 throw new ArgumentException("No transaction name was be specified.");
\r
255 if (this.isUpdated)
\r
257 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
262 FbCommand command = new FbCommand(
\r
263 "RELEASE SAVEPOINT " + savePointName,
\r
266 command.ExecuteNonQuery();
\r
269 catch (IscException ex)
\r
271 throw new FbException(ex.Message, ex);
\r
276 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Rollback(System.String)"]/*'/>
\r
277 public void Rollback(string savePointName)
\r
281 if (savePointName == null)
\r
283 throw new ArgumentException("No transaction name was be specified.");
\r
287 if (savePointName.Length == 0)
\r
289 throw new ArgumentException("No transaction name was be specified.");
\r
292 if (this.isUpdated)
\r
294 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
299 FbCommand command = new FbCommand(
\r
300 "ROLLBACK WORK TO SAVEPOINT " + savePointName,
\r
303 command.ExecuteNonQuery();
\r
306 catch (IscException ex)
\r
308 throw new FbException(ex.Message, ex);
\r
313 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="CommitRetaining"]/*'/>
\r
314 public void CommitRetaining()
\r
318 if (this.isUpdated)
\r
320 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
325 this.transaction.CommitRetaining();
\r
327 catch (IscException ex)
\r
329 throw new FbException(ex.Message, ex);
\r
334 /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="RollbackRetaining"]/*'/>
\r
335 public void RollbackRetaining()
\r
339 if (this.isUpdated)
\r
341 throw new InvalidOperationException("This Transaction has completed; it is no longer usable.");
\r
346 this.transaction.RollbackRetaining();
\r
348 catch (IscException ex)
\r
350 throw new FbException(ex.Message, ex);
\r
357 #region InternalMethods
\r
359 internal void BeginTransaction()
\r
365 IDatabase database = this.connection.InnerConnection.Database;
\r
366 this.transaction = database.BeginTransaction(this.BuildTpb());
\r
368 catch (IscException ex)
\r
370 throw new FbException(ex.Message, ex);
\r
375 internal void BeginTransaction(FbTransactionOptions options)
\r
381 IDatabase database = this.connection.InnerConnection.Database;
\r
382 this.transaction = database.BeginTransaction(this.BuildTpb(options));
\r
384 catch (IscException ex)
\r
386 throw new FbException(ex.Message, ex);
\r
393 #region Private Methods
\r
395 private void UpdateTransaction()
\r
397 if (this.connection != null)
\r
399 this.connection.InnerConnection.TransactionUpdated();
\r
402 this.isUpdated = true;
\r
403 this.connection = null;
\r
404 this.transaction = null;
\r
407 private TransactionParameterBuffer BuildTpb()
\r
409 FbTransactionOptions options = FbTransactionOptions.Write;
\r
411 options |= FbTransactionOptions.Wait;
\r
413 /* Isolation level */
\r
414 switch (this.isolationLevel)
\r
416 case IsolationLevel.Serializable:
\r
417 options |= FbTransactionOptions.Consistency;
\r
420 case IsolationLevel.RepeatableRead:
\r
421 options |= FbTransactionOptions.Concurrency;
\r
424 case IsolationLevel.ReadUncommitted:
\r
425 options |= FbTransactionOptions.ReadCommitted;
\r
426 options |= FbTransactionOptions.RecVersion;
\r
429 case IsolationLevel.ReadCommitted:
\r
431 options |= FbTransactionOptions.ReadCommitted;
\r
432 options |= FbTransactionOptions.NoRecVersion;
\r
436 return this.BuildTpb(options);
\r
441 private TransactionParameterBuffer BuildTpb(FbTransactionOptions options)
\r
443 TransactionParameterBuffer tpb = new TransactionParameterBuffer();
\r
445 tpb.Append(IscCodes.isc_tpb_version3);
\r
447 FbTransactionOptions[] o = (FbTransactionOptions[])Enum.GetValues(options.GetType());
\r
448 for (int i = 0; i < o.Length; i++)
\r
450 FbTransactionOptions option = ((FbTransactionOptions)(o[i]));
\r
451 if ((options & option) == option)
\r
455 case FbTransactionOptions.Consistency:
\r
456 tpb.Append(IscCodes.isc_tpb_consistency);
\r
459 case FbTransactionOptions.Concurrency:
\r
460 tpb.Append(IscCodes.isc_tpb_concurrency);
\r
463 case FbTransactionOptions.Shared:
\r
464 tpb.Append(IscCodes.isc_tpb_shared);
\r
467 case FbTransactionOptions.Protected:
\r
468 tpb.Append(IscCodes.isc_tpb_protected);
\r
471 case FbTransactionOptions.Exclusive:
\r
472 tpb.Append(IscCodes.isc_tpb_exclusive);
\r
475 case FbTransactionOptions.Wait:
\r
476 tpb.Append(IscCodes.isc_tpb_wait);
\r
479 case FbTransactionOptions.NoWait:
\r
480 tpb.Append(IscCodes.isc_tpb_nowait);
\r
483 case FbTransactionOptions.Read:
\r
484 tpb.Append(IscCodes.isc_tpb_read);
\r
487 case FbTransactionOptions.Write:
\r
488 tpb.Append(IscCodes.isc_tpb_write);
\r
491 case FbTransactionOptions.LockRead:
\r
492 tpb.Append(IscCodes.isc_tpb_lock_read);
\r
495 case FbTransactionOptions.LockWrite:
\r
496 tpb.Append(IscCodes.isc_tpb_lock_write);
\r
499 case FbTransactionOptions.ReadCommitted:
\r
500 tpb.Append(IscCodes.isc_tpb_read_committed);
\r
503 case FbTransactionOptions.Autocommit:
\r
504 tpb.Append(IscCodes.isc_tpb_autocommit);
\r
507 case FbTransactionOptions.RecVersion:
\r
508 tpb.Append(IscCodes.isc_tpb_rec_version);
\r
511 case FbTransactionOptions.NoRecVersion:
\r
512 tpb.Append(IscCodes.isc_tpb_no_rec_version);
\r
515 case FbTransactionOptions.RestartRequests:
\r
516 tpb.Append(IscCodes.isc_tpb_restart_requests);
\r
519 case FbTransactionOptions.NoAutoUndo:
\r
520 tpb.Append(IscCodes.isc_tpb_no_auto_undo);
\r
531 private TransactionParameterBuffer BuildTpb(FbTransactionOptions options)
\r
533 TransactionParameterBuffer tpb = new TransactionParameterBuffer();
\r
535 tpb.Append(IscCodes.isc_tpb_version3);
\r
537 if ((options & FbTransactionOptions.Consistency) == FbTransactionOptions.Consistency)
\r
539 tpb.Append(IscCodes.isc_tpb_consistency);
\r
541 if ((options & FbTransactionOptions.Concurrency) == FbTransactionOptions.Concurrency)
\r
543 tpb.Append(IscCodes.isc_tpb_concurrency);
\r
545 if ((options & FbTransactionOptions.Shared) == FbTransactionOptions.Shared)
\r
547 tpb.Append(IscCodes.isc_tpb_shared);
\r
549 if ((options & FbTransactionOptions.Protected) == FbTransactionOptions.Protected)
\r
551 tpb.Append(IscCodes.isc_tpb_protected);
\r
553 if ((options & FbTransactionOptions.Exclusive) == FbTransactionOptions.Exclusive)
\r
555 tpb.Append(IscCodes.isc_tpb_exclusive);
\r
557 if ((options & FbTransactionOptions.Wait) == FbTransactionOptions.Wait)
\r
559 tpb.Append(IscCodes.isc_tpb_wait);
\r
561 if ((options & FbTransactionOptions.NoWait) == FbTransactionOptions.NoWait)
\r
563 tpb.Append(IscCodes.isc_tpb_nowait);
\r
565 if ((options & FbTransactionOptions.Read) == FbTransactionOptions.Read)
\r
567 tpb.Append(IscCodes.isc_tpb_read);
\r
569 if ((options & FbTransactionOptions.Write) == FbTransactionOptions.Write)
\r
571 tpb.Append(IscCodes.isc_tpb_write);
\r
573 if ((options & FbTransactionOptions.LockRead) == FbTransactionOptions.LockRead)
\r
575 tpb.Append(IscCodes.isc_tpb_lock_read);
\r
577 if ((options & FbTransactionOptions.LockWrite) == FbTransactionOptions.LockWrite)
\r
579 tpb.Append(IscCodes.isc_tpb_lock_write);
\r
581 if ((options & FbTransactionOptions.ReadCommitted) == FbTransactionOptions.ReadCommitted)
\r
583 tpb.Append(IscCodes.isc_tpb_read_committed);
\r
585 if ((options & FbTransactionOptions.Autocommit) == FbTransactionOptions.Autocommit)
\r
587 tpb.Append(IscCodes.isc_tpb_autocommit);
\r
589 if ((options & FbTransactionOptions.RecVersion) == FbTransactionOptions.RecVersion)
\r
591 tpb.Append(IscCodes.isc_tpb_rec_version);
\r
593 if ((options & FbTransactionOptions.NoRecVersion) == FbTransactionOptions.NoRecVersion)
\r
595 tpb.Append(IscCodes.isc_tpb_no_rec_version);
\r
597 if ((options & FbTransactionOptions.RestartRequests) == FbTransactionOptions.RestartRequests)
\r
599 tpb.Append(IscCodes.isc_tpb_restart_requests);
\r
601 if ((options & FbTransactionOptions.NoAutoUndo) == FbTransactionOptions.NoAutoUndo)
\r
603 tpb.Append(IscCodes.isc_tpb_no_auto_undo);
\r