OleDbDataReader.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. //
  2. // System.Data.OleDb.OleDbDataReader
  3. //
  4. // Author:
  5. // Rodrigo Moya ([email protected])
  6. // Tim Coleman ([email protected])
  7. //
  8. // Copyright (C) Rodrigo Moya, 2002
  9. // Copyright (C) Tim Coleman, 2002
  10. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System.Collections;
  32. using System.ComponentModel;
  33. using System.Data.Common;
  34. using System.Runtime.InteropServices;
  35. namespace System.Data.OleDb
  36. {
  37. public sealed class OleDbDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable
  38. {
  39. #region Fields
  40. private OleDbCommand command;
  41. private bool open;
  42. private ArrayList gdaResults;
  43. private int currentResult;
  44. private int currentRow;
  45. private bool disposed;
  46. #endregion
  47. #region Constructors
  48. internal OleDbDataReader (OleDbCommand command, ArrayList results)
  49. {
  50. this.command = command;
  51. open = true;
  52. if (results != null)
  53. gdaResults = results;
  54. else
  55. gdaResults = new ArrayList ();
  56. currentResult = -1;
  57. currentRow = -1;
  58. }
  59. #endregion
  60. #region Properties
  61. public int Depth {
  62. get {
  63. return 0; // no nested selects supported
  64. }
  65. }
  66. public int FieldCount {
  67. get {
  68. if (currentResult < 0 || currentResult >= gdaResults.Count)
  69. return 0;
  70. return libgda.gda_data_model_get_n_columns (
  71. (IntPtr) gdaResults[currentResult]);
  72. }
  73. }
  74. public bool IsClosed {
  75. get {
  76. return !open;
  77. }
  78. }
  79. public object this[string name] {
  80. get {
  81. int pos;
  82. if (currentResult == -1)
  83. throw new InvalidOperationException ();
  84. pos = libgda.gda_data_model_get_column_position (
  85. (IntPtr) gdaResults[currentResult],
  86. name);
  87. if (pos == -1)
  88. throw new IndexOutOfRangeException ();
  89. return this[pos];
  90. }
  91. }
  92. public object this[int index] {
  93. get {
  94. return (object) GetValue (index);
  95. }
  96. }
  97. public int RecordsAffected {
  98. get {
  99. int total_rows;
  100. if (currentResult < 0 ||
  101. currentResult >= gdaResults.Count)
  102. return 0;
  103. total_rows = libgda.gda_data_model_get_n_rows (
  104. (IntPtr) gdaResults[currentResult]);
  105. if (total_rows > 0) {
  106. if (FieldCount > 0) {
  107. // It's a SELECT statement
  108. return -1;
  109. }
  110. }
  111. return FieldCount > 0 ? -1 : total_rows;
  112. }
  113. }
  114. [MonoTODO]
  115. public bool HasRows {
  116. get {
  117. throw new NotImplementedException ();
  118. }
  119. }
  120. #endregion
  121. #region Methods
  122. public void Close ()
  123. {
  124. for (int i = 0; i < gdaResults.Count; i++) {
  125. IntPtr obj = (IntPtr) gdaResults[i];
  126. libgda.FreeObject (obj);
  127. }
  128. gdaResults.Clear ();
  129. gdaResults = null;
  130. open = false;
  131. currentResult = -1;
  132. currentRow = -1;
  133. }
  134. public bool GetBoolean (int ordinal)
  135. {
  136. IntPtr value;
  137. if (currentResult == -1)
  138. throw new InvalidCastException ();
  139. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  140. ordinal, currentRow);
  141. if (value == IntPtr.Zero)
  142. throw new InvalidCastException ();
  143. if (libgda.gda_value_get_type (value) != GdaValueType.Boolean)
  144. throw new InvalidCastException ();
  145. return libgda.gda_value_get_boolean (value);
  146. }
  147. public byte GetByte (int ordinal)
  148. {
  149. IntPtr value;
  150. if (currentResult == -1)
  151. throw new InvalidCastException ();
  152. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  153. ordinal, currentRow);
  154. if (value == IntPtr.Zero)
  155. throw new InvalidCastException ();
  156. if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
  157. throw new InvalidCastException ();
  158. return libgda.gda_value_get_tinyint (value);
  159. }
  160. [MonoTODO]
  161. public long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
  162. {
  163. throw new NotImplementedException ();
  164. }
  165. [EditorBrowsableAttribute (EditorBrowsableState.Never)]
  166. public char GetChar (int ordinal)
  167. {
  168. IntPtr value;
  169. if (currentResult == -1)
  170. throw new InvalidCastException ();
  171. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  172. ordinal, currentRow);
  173. if (value == IntPtr.Zero)
  174. throw new InvalidCastException ();
  175. if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
  176. throw new InvalidCastException ();
  177. return (char) libgda.gda_value_get_tinyint (value);
  178. }
  179. [MonoTODO]
  180. public long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
  181. {
  182. throw new NotImplementedException ();
  183. }
  184. [MonoTODO]
  185. public OleDbDataReader GetData (int ordinal)
  186. {
  187. throw new NotImplementedException ();
  188. }
  189. public string GetDataTypeName (int index)
  190. {
  191. IntPtr attrs;
  192. GdaValueType type;
  193. if (currentResult == -1)
  194. return "unknown";
  195. attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
  196. index);
  197. if (attrs == IntPtr.Zero)
  198. return "unknown";
  199. type = libgda.gda_field_attributes_get_gdatype (attrs);
  200. libgda.gda_field_attributes_free (attrs);
  201. return libgda.gda_type_to_string (type);
  202. }
  203. public DateTime GetDateTime (int ordinal)
  204. {
  205. IntPtr value;
  206. DateTime dt;
  207. if (currentResult == -1)
  208. throw new InvalidCastException ();
  209. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  210. ordinal, currentRow);
  211. if (value == IntPtr.Zero)
  212. throw new InvalidCastException ();
  213. if (libgda.gda_value_get_type (value) == GdaValueType.Date) {
  214. GdaDate gdt;
  215. gdt = (GdaDate) Marshal.PtrToStructure (libgda.gda_value_get_date (value),
  216. typeof (GdaDate));
  217. return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day);
  218. } else if (libgda.gda_value_get_type (value) == GdaValueType.Time) {
  219. GdaTime gdt;
  220. gdt = (GdaTime) Marshal.PtrToStructure (libgda.gda_value_get_time (value),
  221. typeof (GdaTime));
  222. return new DateTime (0, 0, 0, (int) gdt.hour, (int) gdt.minute, (int) gdt.second, 0);
  223. } else if (libgda.gda_value_get_type (value) == GdaValueType.Timestamp) {
  224. GdaTimestamp gdt;
  225. gdt = (GdaTimestamp) Marshal.PtrToStructure (libgda.gda_value_get_timestamp (value),
  226. typeof (GdaTimestamp));
  227. return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day,
  228. (int) gdt.hour, (int) gdt.minute, (int) gdt.second,
  229. (int) gdt.fraction);
  230. }
  231. throw new InvalidCastException ();
  232. }
  233. [MonoTODO]
  234. public decimal GetDecimal (int ordinal)
  235. {
  236. throw new NotImplementedException ();
  237. }
  238. public double GetDouble (int ordinal)
  239. {
  240. IntPtr value;
  241. if (currentResult == -1)
  242. throw new InvalidCastException ();
  243. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  244. ordinal, currentRow);
  245. if (value == IntPtr.Zero)
  246. throw new InvalidCastException ();
  247. if (libgda.gda_value_get_type (value) != GdaValueType.Double)
  248. throw new InvalidCastException ();
  249. return libgda.gda_value_get_double (value);
  250. }
  251. [MonoTODO]
  252. public Type GetFieldType (int index)
  253. {
  254. IntPtr value;
  255. GdaValueType type;
  256. if (currentResult == -1)
  257. throw new IndexOutOfRangeException ();
  258. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  259. index, currentRow);
  260. if (value == IntPtr.Zero)
  261. throw new IndexOutOfRangeException ();
  262. type = libgda.gda_value_get_type (value);
  263. switch (type) {
  264. case GdaValueType.Bigint : return typeof (long);
  265. case GdaValueType.Boolean : return typeof (bool);
  266. case GdaValueType.Date : return typeof (DateTime);
  267. case GdaValueType.Double : return typeof (double);
  268. case GdaValueType.Integer : return typeof (int);
  269. case GdaValueType.Single : return typeof (float);
  270. case GdaValueType.Smallint : return typeof (byte);
  271. case GdaValueType.String : return typeof (string);
  272. case GdaValueType.Time : return typeof (DateTime);
  273. case GdaValueType.Timestamp : return typeof (DateTime);
  274. case GdaValueType.Tinyint : return typeof (byte);
  275. }
  276. return typeof(string); // default
  277. }
  278. public float GetFloat (int ordinal)
  279. {
  280. IntPtr value;
  281. if (currentResult == -1)
  282. throw new InvalidCastException ();
  283. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  284. ordinal, currentRow);
  285. if (value == IntPtr.Zero)
  286. throw new InvalidCastException ();
  287. if (libgda.gda_value_get_type (value) != GdaValueType.Single)
  288. throw new InvalidCastException ();
  289. return libgda.gda_value_get_single (value);
  290. }
  291. [MonoTODO]
  292. public Guid GetGuid (int ordinal)
  293. {
  294. throw new NotImplementedException ();
  295. }
  296. public short GetInt16 (int ordinal)
  297. {
  298. IntPtr value;
  299. if (currentResult == -1)
  300. throw new InvalidCastException ();
  301. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  302. ordinal, currentRow);
  303. if (value == IntPtr.Zero)
  304. throw new InvalidCastException ();
  305. if (libgda.gda_value_get_type (value) != GdaValueType.Smallint)
  306. throw new InvalidCastException ();
  307. return (short) libgda.gda_value_get_smallint (value);
  308. }
  309. public int GetInt32 (int ordinal)
  310. {
  311. IntPtr value;
  312. if (currentResult == -1)
  313. throw new InvalidCastException ();
  314. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  315. ordinal, currentRow);
  316. if (value == IntPtr.Zero)
  317. throw new InvalidCastException ();
  318. if (libgda.gda_value_get_type (value) != GdaValueType.Integer)
  319. throw new InvalidCastException ();
  320. return libgda.gda_value_get_integer (value);
  321. }
  322. public long GetInt64 (int ordinal)
  323. {
  324. IntPtr value;
  325. if (currentResult == -1)
  326. throw new InvalidCastException ();
  327. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  328. ordinal, currentRow);
  329. if (value == IntPtr.Zero)
  330. throw new InvalidCastException ();
  331. if (libgda.gda_value_get_type (value) != GdaValueType.Bigint)
  332. throw new InvalidCastException ();
  333. return libgda.gda_value_get_bigint (value);
  334. }
  335. public string GetName (int index)
  336. {
  337. if (currentResult == -1)
  338. return null;
  339. return libgda.gda_data_model_get_column_title (
  340. (IntPtr) gdaResults[currentResult], index);
  341. }
  342. public int GetOrdinal (string name)
  343. {
  344. if (currentResult == -1)
  345. throw new IndexOutOfRangeException ();
  346. for (int i = 0; i < FieldCount; i++) {
  347. if (GetName (i) == name)
  348. return i;
  349. }
  350. throw new IndexOutOfRangeException ();
  351. }
  352. public DataTable GetSchemaTable ()
  353. {
  354. DataTable dataTableSchema = null;
  355. // Only Results from SQL SELECT Queries
  356. // get a DataTable for schema of the result
  357. // otherwise, DataTable is null reference
  358. if(this.FieldCount > 0) {
  359. IntPtr attrs;
  360. GdaValueType gdaType;
  361. long columnSize = 0;
  362. if (currentResult == -1) {
  363. // FIXME: throw an exception?
  364. #if DEBUG_OleDbDataReader
  365. Console.WriteLine("Error: current result -1");
  366. #endif
  367. return null;
  368. }
  369. dataTableSchema = new DataTable ();
  370. dataTableSchema.Columns.Add ("ColumnName", typeof (string));
  371. dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
  372. dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
  373. dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
  374. dataTableSchema.Columns.Add ("NumericScale", typeof (int));
  375. dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
  376. dataTableSchema.Columns.Add ("IsKey", typeof (bool));
  377. DataColumn dc = dataTableSchema.Columns["IsKey"];
  378. dc.AllowDBNull = true; // IsKey can have a DBNull
  379. dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
  380. dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
  381. dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
  382. dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
  383. dataTableSchema.Columns.Add ("DataType", typeof(Type));
  384. dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
  385. dataTableSchema.Columns.Add ("ProviderType", typeof (int));
  386. dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
  387. dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
  388. dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
  389. dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
  390. dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
  391. dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
  392. dataTableSchema.Columns.Add ("IsLong", typeof (bool));
  393. dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
  394. DataRow schemaRow;
  395. DbType dbType;
  396. Type typ;
  397. for (int i = 0; i < this.FieldCount; i += 1 ) {
  398. schemaRow = dataTableSchema.NewRow ();
  399. attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
  400. i);
  401. if (attrs == IntPtr.Zero){
  402. // FIXME: throw exception
  403. #if DEBUG_OleDbDataReader
  404. Console.WriteLine("Error: attrs null");
  405. #endif
  406. return null;
  407. }
  408. gdaType = libgda.gda_field_attributes_get_gdatype (attrs);
  409. columnSize = libgda.gda_field_attributes_get_defined_size (attrs);
  410. libgda.gda_field_attributes_free (attrs);
  411. schemaRow["ColumnName"] = this.GetName(i);
  412. schemaRow["ColumnOrdinal"] = i + 1;
  413. schemaRow["ColumnSize"] = (int) columnSize;
  414. schemaRow["NumericPrecision"] = 0;
  415. schemaRow["NumericScale"] = 0;
  416. // TODO: need to get KeyInfo
  417. //if((cmdBehavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo) {
  418. // bool IsUnique, IsKey;
  419. // GetKeyInfo(field[i].Name, out IsUnique, out IsKey);
  420. //}
  421. //else {
  422. schemaRow["IsUnique"] = false;
  423. schemaRow["IsKey"] = DBNull.Value;
  424. //}
  425. schemaRow["BaseCatalogName"] = "";
  426. schemaRow["BaseColumnName"] = this.GetName(i);
  427. schemaRow["BaseSchemaName"] = "";
  428. schemaRow["BaseTableName"] = "";
  429. schemaRow["DataType"] = this.GetFieldType(i);
  430. schemaRow["AllowDBNull"] = false;
  431. schemaRow["ProviderType"] = (int) gdaType;
  432. schemaRow["IsAliased"] = false;
  433. schemaRow["IsExpression"] = false;
  434. schemaRow["IsIdentity"] = false;
  435. schemaRow["IsAutoIncrement"] = false;
  436. schemaRow["IsRowVersion"] = false;
  437. schemaRow["IsHidden"] = false;
  438. schemaRow["IsLong"] = false;
  439. schemaRow["IsReadOnly"] = false;
  440. schemaRow.AcceptChanges();
  441. dataTableSchema.Rows.Add (schemaRow);
  442. }
  443. #if DEBUG_OleDbDataReader
  444. Console.WriteLine("********** DEBUG Table Schema BEGIN ************");
  445. foreach (DataRow myRow in dataTableSchema.Rows) {
  446. foreach (DataColumn myCol in dataTableSchema.Columns)
  447. Console.WriteLine(myCol.ColumnName + " = " + myRow[myCol]);
  448. Console.WriteLine();
  449. }
  450. Console.WriteLine("********** DEBUG Table Schema END ************");
  451. #endif // DEBUG_OleDbDataReader
  452. }
  453. return dataTableSchema;
  454. }
  455. public string GetString (int ordinal)
  456. {
  457. IntPtr value;
  458. if (currentResult == -1)
  459. throw new InvalidCastException ();
  460. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  461. ordinal, currentRow);
  462. if (value == IntPtr.Zero)
  463. throw new InvalidCastException ();
  464. if (libgda.gda_value_get_type (value) != GdaValueType.String)
  465. throw new InvalidCastException ();
  466. return libgda.gda_value_get_string (value);
  467. }
  468. [MonoTODO]
  469. public TimeSpan GetTimeSpan (int ordinal)
  470. {
  471. throw new NotImplementedException ();
  472. }
  473. public object GetValue (int ordinal)
  474. {
  475. IntPtr value;
  476. GdaValueType type;
  477. if (currentResult == -1)
  478. throw new IndexOutOfRangeException ();
  479. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  480. ordinal, currentRow);
  481. if (value == IntPtr.Zero)
  482. throw new IndexOutOfRangeException ();
  483. type = libgda.gda_value_get_type (value);
  484. switch (type) {
  485. case GdaValueType.Bigint : return GetInt64 (ordinal);
  486. case GdaValueType.Boolean : return GetBoolean (ordinal);
  487. case GdaValueType.Date : return GetDateTime (ordinal);
  488. case GdaValueType.Double : return GetDouble (ordinal);
  489. case GdaValueType.Integer : return GetInt32 (ordinal);
  490. case GdaValueType.Single : return GetFloat (ordinal);
  491. case GdaValueType.Smallint : return GetByte (ordinal);
  492. case GdaValueType.String : return GetString (ordinal);
  493. case GdaValueType.Time : return GetDateTime (ordinal);
  494. case GdaValueType.Timestamp : return GetDateTime (ordinal);
  495. case GdaValueType.Tinyint : return GetByte (ordinal);
  496. }
  497. return (object) libgda.gda_value_stringify (value);
  498. }
  499. [MonoTODO]
  500. public int GetValues (object[] values)
  501. {
  502. throw new NotImplementedException ();
  503. }
  504. [MonoTODO]
  505. IDataReader IDataRecord.GetData (int ordinal)
  506. {
  507. throw new NotImplementedException ();
  508. }
  509. IEnumerator IEnumerable.GetEnumerator ()
  510. {
  511. return new DbEnumerator (this);
  512. }
  513. public bool IsDBNull (int ordinal)
  514. {
  515. IntPtr value;
  516. if (currentResult == -1)
  517. throw new IndexOutOfRangeException ();
  518. value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
  519. ordinal, currentRow);
  520. if (value == IntPtr.Zero)
  521. throw new IndexOutOfRangeException ();
  522. return libgda.gda_value_is_null (value);
  523. }
  524. public bool NextResult ()
  525. {
  526. int i = currentResult + 1;
  527. if (i >= 0 && i < gdaResults.Count) {
  528. currentResult++;
  529. return true;
  530. }
  531. return false;
  532. }
  533. public bool Read ()
  534. {
  535. if (currentResult < 0 || currentResult >= gdaResults.Count)
  536. return false;
  537. currentRow++;
  538. if (currentRow < libgda.gda_data_model_get_n_rows ((IntPtr) gdaResults[currentResult]))
  539. return true;
  540. return false;
  541. }
  542. #endregion
  543. #region Destructors
  544. private void Dispose (bool disposing)
  545. {
  546. if (!this.disposed) {
  547. if (disposing) {
  548. // release any managed resources
  549. command = null;
  550. GC.SuppressFinalize (this);
  551. }
  552. // release any unmanaged resources
  553. if (gdaResults != null) {
  554. gdaResults.Clear ();
  555. gdaResults = null;
  556. }
  557. // close any handles
  558. if (open)
  559. Close ();
  560. this.disposed = true;
  561. }
  562. }
  563. void IDisposable.Dispose() {
  564. Dispose (true);
  565. }
  566. ~OleDbDataReader() {
  567. Dispose (false);
  568. }
  569. #endregion // Destructors
  570. }
  571. }