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