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