2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Npgsql / Npgsql / NpgsqlTransaction.cs
1 // created on 17/11/2002 at 19:04
2
3 // Npgsql.NpgsqlTransaction.cs
4 //
5 // Author:
6 //      Francisco Jr. (fxjrlists@yahoo.com.br)
7 //
8 //      Copyright (C) 2002 The Npgsql Development Team
9 //      npgsql-general@gborg.postgresql.org
10 //      http://gborg.postgresql.org/project/npgsql/projdisplay.php
11 //
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
16 //
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 // Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26
27 using System;
28 using System.Text;
29 using System.Resources;
30 using System.Data;
31
32
33 namespace Npgsql
34 {
35     /// <summary>
36     /// Represents a transaction to be made in a PostgreSQL database. This class cannot be inherited.
37     /// </summary>
38     public sealed class NpgsqlTransaction : MarshalByRefObject, IDbTransaction
39     {
40         private static readonly String CLASSNAME = "NpgsqlTransaction";
41         private static ResourceManager resman = new ResourceManager(typeof(NpgsqlTransaction));
42
43         private NpgsqlConnection    _conn = null;
44         private IsolationLevel      _isolation = IsolationLevel.ReadCommitted;
45         private bool                _disposed = false;
46
47         internal NpgsqlTransaction(NpgsqlConnection conn) : this(conn, IsolationLevel.ReadCommitted)
48         {}
49
50         internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
51         {
52             resman = new System.Resources.ResourceManager(this.GetType());
53
54             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
55             if ((isolation != IsolationLevel.ReadCommitted) &&
56                     (isolation != IsolationLevel.Serializable))
57                 throw new ArgumentOutOfRangeException(resman.GetString("Exception_UnsopportedIsolationLevel"), "isolation");
58
59             _conn = conn;
60             _isolation = isolation;
61
62             StringBuilder commandText = new StringBuilder("SET TRANSACTION ISOLATION LEVEL ");
63
64             if (isolation == IsolationLevel.ReadCommitted)
65                 commandText.Append("READ COMMITTED");
66             else
67                 commandText.Append("SERIALIZABLE");
68
69             commandText.Append("; BEGIN");
70
71             NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);
72             command.ExecuteNonQuery();
73             _conn.Connector.Transaction = this;
74         }
75
76         /// <summary>
77         /// Gets the <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>
78         /// object associated with the transaction, or a null reference if the
79         /// transaction is no longer valid.
80         /// </summary>
81         /// <value>The <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>
82         /// object associated with the transaction.</value>
83         public NpgsqlConnection Connection
84         {
85             get
86             {
87                 return _conn;
88             }
89         }
90
91
92         IDbConnection IDbTransaction.Connection
93         {
94             get
95             {
96                 return Connection;
97             }
98         }
99
100         /// <summary>
101         /// Specifies the <see cref="System.Data.IsolationLevel">IsolationLevel</see> for this transaction.
102         /// </summary>
103         /// <value>The <see cref="System.Data.IsolationLevel">IsolationLevel</see> for this transaction.
104         /// The default is <b>ReadCommitted</b>.</value>
105         public IsolationLevel IsolationLevel
106         {
107             get
108             {
109                 if (_conn == null)
110                 {
111                     throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
112                 }
113
114                 return _isolation;
115             }
116         }
117
118         /// <summary>
119         /// Releases the unmanaged resources used by the
120         /// <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>
121         /// and optionally releases the managed resources.
122         /// </summary>
123         public void Dispose()
124         {
125             GC.SuppressFinalize(this);
126
127             this.Dispose(true);
128         }
129
130         private void Dispose(Boolean disposing)
131         {
132             if(disposing && this._conn != null)
133             {
134                 if (_conn.Connector.Transaction != null)
135                     this.Rollback();
136
137                 this._disposed = true;
138             }
139         }
140
141         /// <summary>
142         /// Commits the database transaction.
143         /// </summary>
144         public void Commit()
145         {
146             CheckDisposed();
147
148             if (_conn == null)
149             {
150                 throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
151             }
152
153             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Commit");
154
155             NpgsqlCommand command = new NpgsqlCommand("COMMIT", _conn.Connector);
156             command.ExecuteNonQuery();
157             _conn.Connector.Transaction = null;
158             _conn = null;
159         }
160
161         /// <summary>
162         /// Rolls back a transaction from a pending state.
163         /// </summary>
164         public void Rollback()
165         {
166             CheckDisposed();
167
168             if (_conn == null)
169             {
170                 throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
171             }
172
173             NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Rollback");
174
175             NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector);
176             command.ExecuteNonQuery();
177             _conn.Connector.Transaction = null;
178             _conn = null;
179         }
180
181         /// <summary>
182         /// Cancel the transaction without telling the backend about it.  This is
183         /// used to make the transaction go away when closing a connection.
184         /// </summary>
185         internal void Cancel()
186         {
187             CheckDisposed();
188
189             if (_conn != null)
190             {
191                 _conn.Connector.Transaction = null;
192                 _conn = null;
193             }
194         }
195
196         internal bool Disposed{
197             get
198             {
199                 return _disposed;
200             }
201         }
202
203
204         internal void CheckDisposed()
205         {
206             if (_disposed)
207                 throw new ObjectDisposedException(CLASSNAME);
208
209         }
210
211         ~NpgsqlTransaction()
212         {
213             Dispose(false);
214         }
215
216     }
217 }