2 // Mono.Data.TdsClient.TdsConnection.cs
5 // Tim Coleman (tim@timcoleman.com)
7 // Copyright (C) 2002 Tim Coleman
10 using Mono.Data.TdsClient.Internal;
12 using System.Collections;
13 using System.Collections.Specialized;
14 using System.ComponentModel;
19 namespace Mono.Data.TdsClient {
20 public class TdsConnection : Component, ICloneable, IDbConnection
24 public static readonly string LibraryName = "Mono.Data.TdsClient";
26 string dataSource; // the database server name
27 int port; // which port to use
28 int packetSize = 512; // what size are the packets we send/receive?
34 string connectionString = null;
36 int connectionTimeout = 15;
37 IsolationLevel isolationLevel = IsolationLevel.ReadCommitted;
39 ConnectionState state = ConnectionState.Closed;
40 TdsConnectionParameters parms = new TdsConnectionParameters ();
41 TdsTransaction transaction = null;
43 // This is the collection of connection pools available
44 static Hashtable pools = new Hashtable ();
45 TdsConnectionPool pool;
47 // Our TDS object, the real workhorse
54 public TdsConnection ()
55 : this (String.Empty, 1433)
59 public TdsConnection (string connectionString)
60 : this (connectionString, 1433)
64 public TdsConnection (string connectionString, int port)
68 parms.Password = null;
69 parms.LibraryName = LibraryName;
70 SetConnectionString (connectionString);
73 #endregion // Constructors
77 public string ConnectionString {
78 get { return connectionString; }
79 set { SetConnectionString (value); }
82 public int ConnectionTimeout {
83 get { return connectionTimeout; }
86 public string Database {
87 get { return tds.Database; }
90 public string DataSource {
91 get { return DataSource; }
94 public int PacketSize {
95 get { return PacketSize; }
98 public string ServerVersion {
100 if (state == ConnectionState.Closed)
101 throw new InvalidOperationException ();
102 return tds.ServerVersion;
106 public ConnectionState State {
107 get { return state; }
114 public string WorkstationId {
115 get { return parms.Hostname; }
118 #endregion // Properties
122 public TdsTransaction BeginTransaction ()
124 return BeginTransaction (IsolationLevel.ReadCommitted);
127 public TdsTransaction BeginTransaction (IsolationLevel il)
129 if (state == ConnectionState.Closed)
130 throw new InvalidOperationException ("Invalid operation. The connection is closed.");
131 if (transaction != null && transaction.Open)
132 throw new InvalidOperationException ("TdsConnection does not support parallel transactions.");
134 transaction = new TdsTransaction (this, il);
138 public void ChangeDatabase (string databaseName)
140 if (Database == databaseName)
142 tds.ExecuteNonQuery (String.Format ("use {0}", databaseName));
147 // rollback any open transactions
148 if (transaction != null && transaction.Open)
149 transaction.Rollback ();
151 // if we aren't pooling, just close the connection
152 // otherwise, relinquish the lock that we established in
153 // the connection pool.
155 pool.ReleaseConnection (tds);
159 this.state = ConnectionState.Closed;
163 protected override void Dispose (bool disposing)
168 public TdsCommand CreateCommand ()
170 return (new TdsCommand (null, this, transaction));
173 object ICloneable.Clone()
175 throw new NotImplementedException ();
178 IDbTransaction IDbConnection.BeginTransaction ()
180 return BeginTransaction ();
183 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel il)
185 return BeginTransaction (il);
188 IDbCommand IDbConnection.CreateCommand ()
190 return CreateCommand ();
195 if (connectionString == null)
196 throw new InvalidOperationException ("The ConnectionString property has not been initialized.");
197 if (parms.User == null)
198 throw new ArgumentException ("User name is null.");
199 if (parms.Password == null)
200 throw new ArgumentException ("Password is null. This may be a bug with blank passwords.");
203 tds = new Tds42 (dataSource, port, packetSize);
205 pool = (TdsConnectionPool) pools[connectionString];
208 pool = new TdsConnectionPool (dataSource, port, packetSize, minPoolSize, maxPoolSize);
209 pools[connectionString] = pool;
212 tds = pool.AllocateConnection ();
215 if (!tds.IsConnected) {
217 ChangeDatabase (parms.Database);
219 this.state = ConnectionState.Open;
223 private void SetConnectionString (string connectionString)
225 connectionString += ";";
226 NameValueCollection parameters = new NameValueCollection ();
228 if (connectionString == String.Empty)
231 bool inQuote = false;
232 bool inDQuote = false;
234 string name = String.Empty;
235 string value = String.Empty;
236 StringBuilder sb = new StringBuilder ();
238 foreach (char c in connectionString)
245 inDQuote = !inDQuote;
248 if (!inDQuote && !inQuote) {
249 value = sb.ToString ();
250 parameters [name.ToUpper ().Trim ()] = value.Trim ();
252 value = String.Empty;
253 sb = new StringBuilder ();
259 if (!inDQuote && !inQuote) {
260 name = sb.ToString ();
261 sb = new StringBuilder ();
272 if (this.ConnectionString == null)
274 SetDefaultConnectionParameters (parameters);
277 SetProperties (parameters);
279 this.connectionString = connectionString;
283 private void SetDefaultConnectionParameters (NameValueCollection parameters)
285 if (null == parameters.Get ("APPLICATION NAME"))
286 parameters["APPLICATION NAME"] = ".Net SqlClient Data Provider";
287 if (null == parameters.Get ("CONNECT TIMEOUT") && null == parameters.Get ("CONNECTION TIMEOUT"))
288 parameters["CONNECT TIMEOUT"] = "15";
289 if (null == parameters.Get ("CONNECTION LIFETIME"))
290 parameters["CONNECTION LIFETIME"] = "0";
291 if (null == parameters.Get ("CONNECTION RESET"))
292 parameters["CONNECTION RESET"] = "true";
293 if (null == parameters.Get ("ENLIST"))
294 parameters["ENLIST"] = "true";
295 if (null == parameters.Get ("INTEGRATED SECURITY") && null == parameters.Get ("TRUSTED_CONNECTION"))
296 parameters["INTEGRATED SECURITY"] = "false";
297 if (null == parameters.Get ("MAX POOL SIZE"))
298 parameters["MAX POOL SIZE"] = "100";
299 if (null == parameters.Get ("MIN POOL SIZE"))
300 parameters["MIN POOL SIZE"] = "0";
301 if (null == parameters.Get ("NETWORK LIBRARY") && null == parameters.Get ("NET"))
302 parameters["NETWORK LIBRARY"] = "dbmssocn";
303 if (null == parameters.Get ("PACKET SIZE"))
304 parameters["PACKET SIZE"] = "512";
305 if (null == parameters.Get ("PERSIST SECURITY INFO"))
306 parameters["PERSIST SECURITY INFO"] = "false";
307 if (null == parameters.Get ("POOLING"))
308 parameters["POOLING"] = "true";
309 if (null == parameters.Get ("WORKSTATION ID"))
310 parameters["WORKSTATION ID"] = Dns.GetHostByName ("localhost").HostName;
313 private void SetProperties (NameValueCollection parameters)
316 foreach (string name in parameters) {
317 value = parameters[name];
320 case "APPLICATION NAME" :
321 parms.ApplicationName = value;
323 case "ATTACHDBFILENAME" :
324 case "EXTENDED PROPERTIES" :
325 case "INITIAL FILE NAME" :
327 case "CONNECT TIMEOUT" :
328 case "CONNECTION TIMEOUT" :
329 connectionTimeout = Int32.Parse (value);
331 case "CONNECTION LIFETIME" :
333 case "CONNECTION RESET" :
334 connectionReset = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
336 case "CURRENT LANGUAGE" :
337 parms.Language = value;
343 case "NETWORK ADDRESS" :
348 case "INITIAL CATALOG" :
350 parms.Database = value;
352 case "INTEGRATED SECURITY" :
353 case "TRUSTED_CONNECTION" :
355 case "MAX POOL SIZE" :
356 maxPoolSize = Int32.Parse (value);
358 case "MIN POOL SIZE" :
359 minPoolSize = Int32.Parse (value);
362 case "NETWORK LIBRARY" :
363 if (!value.ToUpper ().Equals ("DBMSSOCN"))
364 throw new TdsException ("Unsupported network library.");
367 packetSize = Int32.Parse (value);
371 parms.Password = value;
373 case "PERSIST SECURITY INFO" :
376 pooling = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
381 case "WORKSTATION ID" :
382 parms.Hostname = value;
387 #endregion // Methods