OracleConnection.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. //
  2. // OracleConnection.cs
  3. //
  4. // Part of the Mono class libraries at
  5. // mcs/class/System.Data.OracleClient/System.Data.OracleClient
  6. //
  7. // Assembly: System.Data.OracleClient.dll
  8. // Namespace: System.Data.OracleClient
  9. //
  10. // Authors:
  11. // Daniel Morgan <[email protected]>
  12. // Tim Coleman <[email protected]>
  13. //
  14. // Copyright (C) Daniel Morgan, 2002
  15. // Copyright (C) Tim Coleman, 2003
  16. //
  17. // Original source code for setting ConnectionString
  18. // by Tim Coleman <[email protected]>
  19. //
  20. // Copyright (C) Tim Coleman, 2002
  21. //
  22. // Licensed under the MIT/X11 License.
  23. //
  24. using System;
  25. using System.Collections;
  26. using System.Collections.Specialized;
  27. using System.ComponentModel;
  28. using System.Data;
  29. using System.Data.OracleClient.Oci;
  30. using System.Drawing.Design;
  31. using System.EnterpriseServices;
  32. using System.Text;
  33. namespace System.Data.OracleClient
  34. {
  35. internal struct OracleConnectionInfo
  36. {
  37. public string Username;
  38. public string Password;
  39. public string Database;
  40. }
  41. [DefaultEvent ("InfoMessage")]
  42. public sealed class OracleConnection : Component, ICloneable, IDbConnection
  43. {
  44. #region Fields
  45. OciGlue oci;
  46. ConnectionState state;
  47. OracleConnectionInfo conInfo;
  48. OracleTransaction transaction = null;
  49. string connectionString = "";
  50. OracleDataReader dataReader = null;
  51. #endregion // Fields
  52. #region Constructors
  53. public OracleConnection ()
  54. {
  55. state = ConnectionState.Closed;
  56. oci = new OciGlue ();
  57. }
  58. public OracleConnection (string connectionString)
  59. : this()
  60. {
  61. SetConnectionString (connectionString);
  62. }
  63. #endregion // Constructors
  64. #region Properties
  65. int IDbConnection.ConnectionTimeout {
  66. [MonoTODO]
  67. get { return -1; }
  68. }
  69. string IDbConnection.Database {
  70. [MonoTODO]
  71. get { return String.Empty; }
  72. }
  73. internal OracleDataReader DataReader {
  74. get { return dataReader; }
  75. set { dataReader = value; }
  76. }
  77. internal OciEnvironmentHandle Environment {
  78. get { return oci.Environment; }
  79. }
  80. internal OciErrorHandle ErrorHandle {
  81. get { return oci.ErrorHandle; }
  82. }
  83. internal OciServiceHandle ServiceContext {
  84. get { return oci.ServiceContext; }
  85. }
  86. [MonoTODO]
  87. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  88. public string DataSource {
  89. get {
  90. return conInfo.Database;
  91. }
  92. }
  93. [Browsable (false)]
  94. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  95. public ConnectionState State {
  96. get { return state; }
  97. }
  98. [DefaultValue ("")]
  99. [RecommendedAsConfigurable (true)]
  100. [RefreshProperties (RefreshProperties.All)]
  101. [Editor ("Microsoft.VSDesigner.Data.Oracle.Design.OracleConnectionStringEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
  102. public string ConnectionString {
  103. get { return connectionString; }
  104. set { SetConnectionString (value); }
  105. }
  106. [MonoTODO]
  107. [Browsable (false)]
  108. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  109. public string ServerVersion {
  110. get {
  111. if (this.State != ConnectionState.Open)
  112. throw new System.InvalidOperationException ("Invalid operation. The connection is closed.");
  113. return GetOracleVersion ();
  114. }
  115. }
  116. internal string GetOracleVersion ()
  117. {
  118. byte[] buffer = new Byte[256];
  119. uint bufflen = (uint) buffer.Length;
  120. IntPtr sh = oci.ServiceContext;
  121. IntPtr eh = oci.ErrorHandle;
  122. OciCalls.OCIServerVersion (sh,
  123. eh,
  124. ref buffer, bufflen,
  125. OciHandleType.Service);
  126. // Get length of returned string
  127. int rsize = 0;
  128. IntPtr env = oci.Environment;
  129. OciCalls.OCICharSetToUnicode (env, null, buffer, out rsize);
  130. // Get string
  131. StringBuilder ret = new StringBuilder(rsize);
  132. OciCalls.OCICharSetToUnicode (env, ret, buffer, out rsize);
  133. return ret.ToString ();
  134. }
  135. internal OciGlue Oci {
  136. get { return oci; }
  137. }
  138. internal OracleTransaction Transaction {
  139. get { return transaction; }
  140. set { transaction = value; }
  141. }
  142. #endregion // Properties
  143. #region Methods
  144. public OracleTransaction BeginTransaction ()
  145. {
  146. return BeginTransaction (IsolationLevel.ReadCommitted);
  147. }
  148. public OracleTransaction BeginTransaction (IsolationLevel il)
  149. {
  150. if (state == ConnectionState.Closed)
  151. throw new InvalidOperationException ("The connection is not open.");
  152. if (transaction != null)
  153. throw new InvalidOperationException ("OracleConnection does not support parallel transactions.");
  154. OciTransactionHandle transactionHandle = oci.CreateTransaction ();
  155. if (transactionHandle == null)
  156. throw new Exception("Error: Unable to start transaction");
  157. else {
  158. transactionHandle.Begin ();
  159. transaction = new OracleTransaction (this, il, transactionHandle);
  160. }
  161. return transaction;
  162. }
  163. [MonoTODO]
  164. void IDbConnection.ChangeDatabase (string databaseName)
  165. {
  166. throw new NotImplementedException ();
  167. }
  168. public OracleCommand CreateCommand ()
  169. {
  170. OracleCommand command = new OracleCommand ();
  171. command.Connection = this;
  172. return command;
  173. }
  174. [MonoTODO]
  175. object ICloneable.Clone ()
  176. {
  177. OracleConnection con = new OracleConnection ();
  178. con.ConnectionString = this.ConnectionString;
  179. if (this.State == ConnectionState.Open)
  180. con.Open ();
  181. // TODO: what other properties need to be cloned?
  182. return con;
  183. }
  184. IDbTransaction IDbConnection.BeginTransaction ()
  185. {
  186. return BeginTransaction ();
  187. }
  188. IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
  189. {
  190. return BeginTransaction (iso);
  191. }
  192. IDbCommand IDbConnection.CreateCommand ()
  193. {
  194. return CreateCommand ();
  195. }
  196. void IDisposable.Dispose ()
  197. {
  198. Dispose (true);
  199. GC.SuppressFinalize (this);
  200. }
  201. [MonoTODO]
  202. protected override void Dispose (bool disposing)
  203. {
  204. base.Dispose (disposing);
  205. }
  206. [MonoTODO]
  207. public void EnlistDistributedTransaction (ITransaction distributedTransaction)
  208. {
  209. throw new NotImplementedException ();
  210. }
  211. public void Open ()
  212. {
  213. oci.CreateConnection (conInfo);
  214. state = ConnectionState.Open;
  215. CreateStateChange (ConnectionState.Closed, ConnectionState.Open);
  216. }
  217. internal void CreateInfoMessage (OciErrorInfo info)
  218. {
  219. OracleInfoMessageEventArgs a = new OracleInfoMessageEventArgs (info);
  220. OnInfoMessage (a);
  221. }
  222. private void OnInfoMessage (OracleInfoMessageEventArgs e)
  223. {
  224. if (InfoMessage != null)
  225. InfoMessage (this, e);
  226. }
  227. internal void CreateStateChange (ConnectionState original, ConnectionState current)
  228. {
  229. StateChangeEventArgs a = new StateChangeEventArgs (original, current);
  230. OnStateChange (a);
  231. }
  232. private void OnStateChange (StateChangeEventArgs e)
  233. {
  234. if (StateChange != null)
  235. StateChange (this, e);
  236. }
  237. public void Close ()
  238. {
  239. if (transaction != null)
  240. transaction.Rollback ();
  241. oci.Disconnect ();
  242. state = ConnectionState.Closed;
  243. CreateStateChange (ConnectionState.Open, ConnectionState.Closed);
  244. }
  245. void SetConnectionString (string connectionString)
  246. {
  247. this.connectionString = connectionString;
  248. conInfo.Username = "";
  249. conInfo.Database = "";
  250. conInfo.Password = "";
  251. if (connectionString == String.Empty)
  252. return;
  253. connectionString += ";";
  254. NameValueCollection parameters = new NameValueCollection ();
  255. bool inQuote = false;
  256. bool inDQuote = false;
  257. string name = String.Empty;
  258. string value = String.Empty;
  259. StringBuilder sb = new StringBuilder ();
  260. foreach (char c in connectionString) {
  261. switch (c) {
  262. case '\'':
  263. inQuote = !inQuote;
  264. break;
  265. case '"' :
  266. inDQuote = !inDQuote;
  267. break;
  268. case ';' :
  269. if (!inDQuote && !inQuote) {
  270. if (name != String.Empty && name != null) {
  271. value = sb.ToString ();
  272. parameters [name.ToUpper ().Trim ()] = value.Trim ();
  273. }
  274. name = String.Empty;
  275. value = String.Empty;
  276. sb = new StringBuilder ();
  277. }
  278. else
  279. sb.Append (c);
  280. break;
  281. case '=' :
  282. if (!inDQuote && !inQuote) {
  283. name = sb.ToString ();
  284. sb = new StringBuilder ();
  285. }
  286. else
  287. sb.Append (c);
  288. break;
  289. default:
  290. sb.Append (c);
  291. break;
  292. }
  293. }
  294. SetProperties (parameters);
  295. }
  296. private void SetProperties (NameValueCollection parameters)
  297. {
  298. string value;
  299. foreach (string name in parameters) {
  300. value = parameters[name];
  301. switch (name) {
  302. case "DATA SOURCE" :
  303. case "SERVER" :
  304. conInfo.Database = value;
  305. break;
  306. case "PASSWORD" :
  307. case "PWD" :
  308. conInfo.Password = value;
  309. break;
  310. case "UID" :
  311. case "USER ID" :
  312. conInfo.Username = value;
  313. break;
  314. default:
  315. throw new ArgumentException("Connection parameter not supported: '" + name + "'");
  316. }
  317. }
  318. }
  319. #endregion // Methods
  320. public event OracleInfoMessageEventHandler InfoMessage;
  321. public event StateChangeEventHandler StateChange;
  322. }
  323. }