This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / IBM.Data.DB2 / IBM.Data.DB2 / DB2Connection.cs
1
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 using System;
23 using System.Collections;
24 using System.Collections.Specialized;
25 using System.Data;
26 using System.Runtime.InteropServices;
27 using System.Text;
28
29 namespace IBM.Data.DB2
30 {
31
32         
33         public class DB2Connection : System.ComponentModel.Component, IDbConnection, ICloneable
34         {
35                 #region private data members
36
37                 private ArrayList refCommands;\r
38                 private WeakReference refTransaction;\r
39                 private DB2ConnectionSettings connectionSettings = null;\r
40                 private int connectionTimeout;\r
41                 internal DB2OpenConnection openConnection;\r
42                 private bool disposed = false;
43
44                 #endregion
45
46                 #region Constructors
47
48                 public DB2Connection()
49                 {
50                         connectionTimeout = 15;
51                         
52                 }
53                 
54                 public DB2Connection(string conString)
55                 {
56                         
57                         SetConnectionString(conString);
58                 }
59
60
61                 #endregion
62                 
63                 #region ConnectionString property
64
65                 public string ConnectionString 
66                 {
67                         get
68                         {
69                                 return connectionSettings.ConnectionString;
70                         }
71                         set
72                         {
73                                 SetConnectionString(value);
74                         }
75                 }
76                 #endregion
77
78
79                 #region ConnectionTimeout property
80                 public int ConnectionTimeout
81                 {
82                         get
83                         {
84                                 return connectionTimeout;
85                         }
86                         set
87                         {
88                                 connectionTimeout = value;
89                         }
90                 }
91                 #endregion
92
93                 #region Database property
94                 public string Database
95                 {
96                         get
97                         {
98                                 return connectionSettings.DatabaseAlias;
99                         }
100                 }
101                 #endregion
102         
103                 #region State property
104
105
106                 unsafe public ConnectionState State
107                 {
108                         get
109                         {   
110                                 //if ((long)dbHandle.ToPointer() == DB2Constants.SQL_NULL_HANDLE)
111                                 if (openConnection == null)
112                                         return ConnectionState.Closed;
113                                 return ConnectionState.Open;
114                         }
115                 }
116                 #endregion
117
118                 #region events\r
119 \r
120                 public event DB2InfoMessageEventHandler InfoMessage;\r
121                 public event StateChangeEventHandler StateChange;\r
122 \r
123                 internal void OnInfoMessage(short handleType, IntPtr handle)\r
124                 {\r
125                         if(InfoMessage != null)\r
126                         {\r
127                                 // Don't get error information until we know for sure someone is listening\r
128                                 try\r
129                                 {\r
130                                         InfoMessage(this,\r
131                                                 new DB2InfoMessageEventArgs(new DB2ErrorCollection(handleType, handle)));\r
132                                 }\r
133                                 catch(Exception)\r
134                                 {}\r
135                         }\r
136                 }\r
137 \r
138                 private void OnStateChange(StateChangeEventArgs args)\r
139                 {\r
140                         if(StateChange != null)\r
141                                 StateChange(this, args);\r
142                 }\r
143 \r
144                 #endregion
145                 
146                 #region DBHandle
147
148                 internal IntPtr DBHandle
149                 {
150                         get
151                         {
152                                 return (openConnection == null) ? IntPtr.Zero : openConnection.DBHandle;
153                         }
154                 }
155                 #endregion
156
157                 #region BeginTransaction Method
158
159                 IDbTransaction IDbConnection.BeginTransaction()
160                 {
161                         return BeginTransaction();
162                 }
163
164                 IDbTransaction IDbConnection.BeginTransaction(IsolationLevel isolationL)
165                 {
166                         return BeginTransaction(isolationL);
167                 }
168
169                 public DB2Transaction BeginTransaction()
170                 {
171                         return BeginTransaction(IsolationLevel.ReadCommitted);
172                 }
173
174                 public DB2Transaction BeginTransaction(IsolationLevel isolationL)
175                 {\r
176                         if ((refTransaction != null) && (refTransaction.IsAlive))\r
177                                 throw new InvalidOperationException("Cannot open another transaction");\r
178                         if(State != ConnectionState.Open)\r
179                                 throw new InvalidOperationException("BeginTransaction needs an open connection");\r
180 \r
181                         if(refTransaction != null)\r
182                         {\r
183                                 if(refTransaction.IsAlive)\r
184                                         throw new InvalidOperationException("Parallel transactions not supported");\r
185 \r
186                                 openConnection.RollbackDeadTransaction();\r
187                                 refTransaction = null;\r
188                         }\r
189                         openConnection.transactionOpen = true;\r
190                         DB2Transaction tran = new DB2Transaction(this, isolationL);\r
191                         refTransaction = new WeakReference(tran);\r
192                         return tran;\r
193                 }
194
195                 #endregion
196                 
197                 #region ChangeDatabase
198                 unsafe public void ChangeDatabase(string newDBName)\r
199                 {\r
200                         if(connectionSettings == null)\r
201                         {\r
202                                 throw new InvalidOperationException("No connection string");\r
203                         }\r
204                         this.Close();\r
205 \r
206                         SetConnectionString(connectionSettings.ConnectionString.Replace(connectionSettings.DatabaseAlias, newDBName));\r
207 \r
208                         this.Open();\r
209                 }
210                 #endregion
211
212                 #region ReleaseObjectPool
213                 public static void ReleaseObjectPool()\r
214                 {\r
215                         DB2Environment.Instance.Dispose();\r
216                 }
217                 #endregion
218                 
219                 #region Close
220                 public void Close()\r
221                 {\r
222                         DB2Transaction transaction = null;\r
223                         if(refTransaction != null)\r
224                                 transaction = (DB2Transaction)refTransaction.Target;\r
225                         if((transaction != null) && refTransaction.IsAlive)\r
226                         {\r
227                                 transaction.Dispose();\r
228                         }\r
229                         if(refCommands != null)\r
230                         {\r
231                                 for(int i = 0; i < refCommands.Count; i++)\r
232                                 {\r
233                                         DB2Command command = null;\r
234                                         if(refCommands[i] != null)\r
235                                         {\r
236                                                 command = (DB2Command)((WeakReference)refCommands[i]).Target;\r
237                                         }\r
238                                         if((command != null) && ((WeakReference)refCommands[i]).IsAlive)\r
239                                         {\r
240                                                 try\r
241                                                 {\r
242                                                         command.ConnectionClosed();\r
243                                                 }\r
244                                                 catch{}\r
245                                         }\r
246                                         //?? refCommands[i] = null;\r
247                                 }\r
248                         }\r
249 \r
250                         if(openConnection != null)\r
251                         {\r
252                                 openConnection.Close();\r
253                                 openConnection = null;\r
254                         }\r
255                 }\r
256
257                 #endregion
258                 
259                 #region CreateCommand
260                 IDbCommand IDbConnection.CreateCommand()
261                 {
262                         return CreateCommand();
263                 }
264
265                 public DB2Command CreateCommand()
266                 {
267                         //CheckState();
268                         return new DB2Command(null, this);
269                 }
270                 #endregion
271                 
272                 #region Open
273
274                 unsafe public void Open()\r
275                 {\r
276                         if(disposed)\r
277                         {\r
278                                 throw new ObjectDisposedException("DB2Connection");\r
279                         }\r
280 \r
281                         if (this.State == ConnectionState.Open || this.State == ConnectionState.Connecting || this.State == ConnectionState.Executing || this.State == ConnectionState.Fetching)\r
282                         {\r
283                                 throw new InvalidOperationException("Connection already open");\r
284                         }\r
285 \r
286                         try\r
287                         {\r
288                                 openConnection = connectionSettings.GetRealOpenConnection(this);\r
289                         }\r
290                         catch (DB2Exception)\r
291                         {\r
292                                 Close();\r
293                                 throw;\r
294                         }\r
295                 }
296                 #endregion
297                 
298                 #region Dispose
299                 public new void Dispose()\r
300                 {\r
301                         Dispose(true);\r
302                         GC.SuppressFinalize(this);\r
303                 }\r
304 \r
305                 protected override void Dispose(bool disposing)\r
306                 {\r
307                         if(!disposed) \r
308                         {\r
309                                 if(disposing)\r
310                                 {\r
311                                         // dispose managed resources\r
312                                         Close();\r
313                                 }\r
314                         }\r
315                         base.Dispose(disposing);\r
316                         disposed = true;\r
317                 }\r
318 \r
319 \r
320                 ~DB2Connection()\r
321                 {\r
322                         Dispose(false);\r
323                 }
324                 #endregion
325
326                 private void CheckState()\r
327                 {\r
328                         if (ConnectionState.Closed == State)\r
329                                 throw new InvalidOperationException("Connection is currently closed.");\r
330                 }\r
331 \r
332                 void SetConnectionString (string connectionString) \r
333                 {\r
334                         if (State != ConnectionState.Closed)\r
335                                 throw new InvalidOperationException("Connection is not closed.");\r
336 \r
337                         this.connectionSettings = DB2ConnectionSettings.GetConnectionSettings(connectionString);\r
338                 }\r
339 \r
340                 internal WeakReference WeakRefTransaction\r
341                 {\r
342                         get\r
343                         {\r
344                                 return refTransaction;\r
345                         }\r
346                         set\r
347                         {\r
348                                 refTransaction = value;\r
349                         }\r
350 \r
351                 }\r
352 \r
353                 internal void AddCommand(DB2Command command)\r
354                 {\r
355                         if(refCommands == null)\r
356                         {\r
357                                 refCommands = new ArrayList();\r
358                         }\r
359                         for(int i = 0; i < refCommands.Count; i++)\r
360                         {\r
361                                 WeakReference reference = (WeakReference)refCommands[i];\r
362                                 if((reference == null) || !reference.IsAlive)\r
363                                 {\r
364                                         refCommands[i] = new WeakReference(command);\r
365                                         return;\r
366                                 }\r
367                         }\r
368                         refCommands.Add(new WeakReference(command));\r
369 \r
370                 }\r
371 \r
372                 internal void RemoveCommand(DB2Command command)\r
373                 {\r
374                         for(int i = 0; i < refCommands.Count; i++)\r
375                         {\r
376                                 WeakReference reference = (WeakReference)refCommands[i];\r
377                                 if(object.ReferenceEquals(reference, command))\r
378                                 {\r
379                                         refCommands[i] = null;\r
380                                         return;\r
381                                 }\r
382                         }\r
383                 }
384
385                 #region ICloneable Members\r
386 \r
387                 object ICloneable.Clone()\r
388                 {\r
389                         DB2Connection clone = new DB2Connection();\r
390 \r
391                         clone.connectionSettings = connectionSettings;\r
392                         clone.connectionTimeout = connectionTimeout;\r
393                         \r
394                         return clone;\r
395                 }\r
396 \r
397                 #endregion
398
399         }
400 }
401