SqlDataReader.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. //
  2. // System.Data.SqlClient.SqlDataReader.cs
  3. //
  4. // Author:
  5. // Rodrigo Moya ([email protected])
  6. // Daniel Morgan ([email protected])
  7. // Tim Coleman ([email protected])
  8. //
  9. // (C) Ximian, Inc 2002
  10. // (C) Daniel Morgan 2002
  11. // Copyright (C) Tim Coleman, 2002
  12. //
  13. //
  14. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  15. //
  16. // Permission is hereby granted, free of charge, to any person obtaining
  17. // a copy of this software and associated documentation files (the
  18. // "Software"), to deal in the Software without restriction, including
  19. // without limitation the rights to use, copy, modify, merge, publish,
  20. // distribute, sublicense, and/or sell copies of the Software, and to
  21. // permit persons to whom the Software is furnished to do so, subject to
  22. // the following conditions:
  23. //
  24. // The above copyright notice and this permission notice shall be
  25. // included in all copies or substantial portions of the Software.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  28. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  29. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  30. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  31. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  32. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  33. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34. //
  35. using Mono.Data.Tds.Protocol;
  36. using System;
  37. using System.Collections;
  38. using System.ComponentModel;
  39. using System.Data;
  40. using System.Data.Common;
  41. using System.Data.SqlTypes;
  42. namespace System.Data.SqlClient {
  43. public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
  44. {
  45. #region Fields
  46. SqlCommand command;
  47. ArrayList dataTypeNames;
  48. bool disposed = false;
  49. int fieldCount;
  50. bool isClosed;
  51. bool isSelect;
  52. bool moreResults;
  53. int resultsRead;
  54. int rowsRead;
  55. DataTable schemaTable;
  56. bool hasRows;
  57. bool haveRead;
  58. bool readResult;
  59. bool readResultUsed;
  60. #endregion // Fields
  61. #region Constructors
  62. internal SqlDataReader (SqlCommand command)
  63. {
  64. readResult = false;
  65. haveRead = false;
  66. readResultUsed = false;
  67. this.command = command;
  68. schemaTable = ConstructSchemaTable ();
  69. resultsRead = 0;
  70. fieldCount = 0;
  71. isClosed = false;
  72. isSelect = (command.CommandText.Trim ().ToUpper ().StartsWith ("SELECT"));
  73. command.Tds.RecordsAffected = 0;
  74. NextResult ();
  75. }
  76. #endregion // Constructors
  77. #region Properties
  78. public int Depth {
  79. get { return 0; }
  80. }
  81. public int FieldCount {
  82. get { return fieldCount; }
  83. }
  84. public bool IsClosed {
  85. get { return isClosed; }
  86. }
  87. public object this [int i] {
  88. get { return GetValue (i); }
  89. }
  90. public object this [string name] {
  91. get { return GetValue (GetOrdinal (name)); }
  92. }
  93. public int RecordsAffected {
  94. get {
  95. if (isSelect)
  96. return -1;
  97. else
  98. return command.Tds.RecordsAffected;
  99. }
  100. }
  101. public bool HasRows {
  102. get {
  103. if (haveRead)
  104. return readResult;
  105. haveRead = true;
  106. readResult = ReadRecord ();
  107. return readResult;
  108. }
  109. }
  110. #endregion // Properties
  111. #region Methods
  112. public void Close ()
  113. {
  114. isClosed = true;
  115. command.Connection.DataReader = null;
  116. command.CloseDataReader (moreResults);
  117. }
  118. private static DataTable ConstructSchemaTable ()
  119. {
  120. Type booleanType = Type.GetType ("System.Boolean");
  121. Type stringType = Type.GetType ("System.String");
  122. Type intType = Type.GetType ("System.Int32");
  123. Type typeType = Type.GetType ("System.Type");
  124. Type shortType = Type.GetType ("System.Int16");
  125. DataTable schemaTable = new DataTable ("SchemaTable");
  126. schemaTable.Columns.Add ("ColumnName", stringType);
  127. schemaTable.Columns.Add ("ColumnOrdinal", intType);
  128. schemaTable.Columns.Add ("ColumnSize", intType);
  129. schemaTable.Columns.Add ("NumericPrecision", shortType);
  130. schemaTable.Columns.Add ("NumericScale", shortType);
  131. schemaTable.Columns.Add ("IsUnique", booleanType);
  132. schemaTable.Columns.Add ("IsKey", booleanType);
  133. schemaTable.Columns.Add ("BaseServerName", stringType);
  134. schemaTable.Columns.Add ("BaseCatalogName", stringType);
  135. schemaTable.Columns.Add ("BaseColumnName", stringType);
  136. schemaTable.Columns.Add ("BaseSchemaName", stringType);
  137. schemaTable.Columns.Add ("BaseTableName", stringType);
  138. schemaTable.Columns.Add ("DataType", typeType);
  139. schemaTable.Columns.Add ("AllowDBNull", booleanType);
  140. schemaTable.Columns.Add ("ProviderType", intType);
  141. schemaTable.Columns.Add ("IsAliased", booleanType);
  142. schemaTable.Columns.Add ("IsExpression", booleanType);
  143. schemaTable.Columns.Add ("IsIdentity", booleanType);
  144. schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
  145. schemaTable.Columns.Add ("IsRowVersion", booleanType);
  146. schemaTable.Columns.Add ("IsHidden", booleanType);
  147. schemaTable.Columns.Add ("IsLong", booleanType);
  148. schemaTable.Columns.Add ("IsReadOnly", booleanType);
  149. return schemaTable;
  150. }
  151. private void Dispose (bool disposing)
  152. {
  153. if (!disposed) {
  154. if (disposing) {
  155. schemaTable.Dispose ();
  156. Close ();
  157. command = null;
  158. }
  159. disposed = true;
  160. }
  161. }
  162. public bool GetBoolean (int i)
  163. {
  164. object value = GetValue (i);
  165. if (!(value is bool)) {
  166. if (value is DBNull) throw new SqlNullValueException ();
  167. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  168. }
  169. return (bool) value;
  170. }
  171. public byte GetByte (int i)
  172. {
  173. object value = GetValue (i);
  174. if (!(value is byte)) {
  175. if (value is DBNull) throw new SqlNullValueException ();
  176. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  177. }
  178. return (byte) value;
  179. }
  180. public long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
  181. {
  182. object value = GetValue (i);
  183. if (!(value is byte [])) {
  184. if (value is DBNull) throw new SqlNullValueException ();
  185. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  186. }
  187. if ( buffer == null ) {
  188. // Return length of data
  189. return ((byte []) value).Length;
  190. }
  191. else {
  192. // Copy data into buffer
  193. Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
  194. return ((byte []) value).Length - dataIndex;
  195. }
  196. }
  197. [EditorBrowsableAttribute (EditorBrowsableState.Never)]
  198. public char GetChar (int i)
  199. {
  200. object value = GetValue (i);
  201. if (!(value is char)) {
  202. if (value is DBNull) throw new SqlNullValueException ();
  203. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  204. }
  205. return (char) value;
  206. }
  207. public long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
  208. {
  209. object value = GetValue (i);
  210. char [] valueBuffer;
  211. if (value is char[])
  212. valueBuffer = (char[])value;
  213. else if (value is string)
  214. valueBuffer = ((string)value).ToCharArray();
  215. else {
  216. if (value is DBNull) throw new SqlNullValueException ();
  217. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  218. }
  219. if ( buffer == null ) {
  220. // Return length of data
  221. return valueBuffer.Length;
  222. }
  223. else {
  224. // Copy data into buffer
  225. Array.Copy (valueBuffer, (int) dataIndex, buffer, bufferIndex, length);
  226. return valueBuffer.Length - dataIndex;
  227. }
  228. }
  229. [EditorBrowsableAttribute (EditorBrowsableState.Never)]
  230. public IDataReader GetData (int i)
  231. {
  232. return ( (IDataReader) this [i]);
  233. }
  234. public string GetDataTypeName (int i)
  235. {
  236. return (string) dataTypeNames [i];
  237. }
  238. public DateTime GetDateTime (int i)
  239. {
  240. object value = GetValue (i);
  241. if (!(value is DateTime)) {
  242. if (value is DBNull) throw new SqlNullValueException ();
  243. else throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  244. }
  245. return (DateTime) value;
  246. }
  247. public decimal GetDecimal (int i)
  248. {
  249. object value = GetValue (i);
  250. if (!(value is decimal)) {
  251. if (value is DBNull) throw new SqlNullValueException ();
  252. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  253. }
  254. return (decimal) value;
  255. }
  256. public double GetDouble (int i)
  257. {
  258. object value = GetValue (i);
  259. if (!(value is double)) {
  260. if (value is DBNull) throw new SqlNullValueException ();
  261. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  262. }
  263. return (double) value;
  264. }
  265. public Type GetFieldType (int i)
  266. {
  267. return (Type) schemaTable.Rows[i]["DataType"];
  268. }
  269. public float GetFloat (int i)
  270. {
  271. object value = GetValue (i);
  272. if (!(value is float)) {
  273. if (value is DBNull) throw new SqlNullValueException ();
  274. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  275. }
  276. return (float) value;
  277. }
  278. public Guid GetGuid (int i)
  279. {
  280. object value = GetValue (i);
  281. if (!(value is Guid)) {
  282. if (value is DBNull) throw new SqlNullValueException ();
  283. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  284. }
  285. return (Guid) value;
  286. }
  287. public short GetInt16 (int i)
  288. {
  289. object value = GetValue (i);
  290. if (!(value is short)) {
  291. if (value is DBNull) throw new SqlNullValueException ();
  292. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  293. }
  294. return (short) value;
  295. }
  296. public int GetInt32 (int i)
  297. {
  298. object value = GetValue (i);
  299. if (!(value is int)) {
  300. if (value is DBNull) throw new SqlNullValueException ();
  301. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  302. }
  303. return (int) value;
  304. }
  305. public long GetInt64 (int i)
  306. {
  307. object value = GetValue (i);
  308. if (!(value is long)) {
  309. if (value is DBNull) throw new SqlNullValueException ();
  310. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  311. }
  312. return (long) value;
  313. }
  314. public string GetName (int i)
  315. {
  316. return (string) schemaTable.Rows[i]["ColumnName"];
  317. }
  318. public int GetOrdinal (string name)
  319. {
  320. foreach (DataRow schemaRow in schemaTable.Rows)
  321. if (((string) schemaRow ["ColumnName"]).Equals (name))
  322. return (int) schemaRow ["ColumnOrdinal"];
  323. foreach (DataRow schemaRow in schemaTable.Rows)
  324. if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
  325. return (int) schemaRow ["ColumnOrdinal"];
  326. throw new IndexOutOfRangeException ();
  327. }
  328. public DataTable GetSchemaTable ()
  329. {
  330. if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
  331. return schemaTable;
  332. if (!moreResults)
  333. return null;
  334. fieldCount = 0;
  335. dataTypeNames = new ArrayList ();
  336. foreach (TdsDataColumn schema in command.Tds.Columns) {
  337. DataRow row = schemaTable.NewRow ();
  338. row ["ColumnName"] = GetSchemaValue (schema, "ColumnName");
  339. row ["ColumnSize"] = GetSchemaValue (schema, "ColumnSize");
  340. row ["ColumnOrdinal"] = GetSchemaValue (schema, "ColumnOrdinal");
  341. row ["NumericPrecision"] = GetSchemaValue (schema, "NumericPrecision");
  342. row ["NumericScale"] = GetSchemaValue (schema, "NumericScale");
  343. row ["IsUnique"] = GetSchemaValue (schema, "IsUnique");
  344. row ["IsKey"] = GetSchemaValue (schema, "IsKey");
  345. row ["BaseServerName"] = GetSchemaValue (schema, "BaseServerName");
  346. row ["BaseCatalogName"] = GetSchemaValue (schema, "BaseCatalogName");
  347. row ["BaseColumnName"] = GetSchemaValue (schema, "BaseColumnName");
  348. row ["BaseSchemaName"] = GetSchemaValue (schema, "BaseSchemaName");
  349. row ["BaseTableName"] = GetSchemaValue (schema, "BaseTableName");
  350. row ["AllowDBNull"] = GetSchemaValue (schema, "AllowDBNull");
  351. row ["IsAliased"] = GetSchemaValue (schema, "IsAliased");
  352. row ["IsExpression"] = GetSchemaValue (schema, "IsExpression");
  353. row ["IsIdentity"] = GetSchemaValue (schema, "IsIdentity");
  354. row ["IsAutoIncrement"] = GetSchemaValue (schema, "IsAutoIncrement");
  355. row ["IsRowVersion"] = GetSchemaValue (schema, "IsRowVersion");
  356. row ["IsHidden"] = GetSchemaValue (schema, "IsHidden");
  357. row ["IsReadOnly"] = GetSchemaValue (schema, "IsReadOnly");
  358. // We don't always get the base column name.
  359. if (row ["BaseColumnName"] == DBNull.Value)
  360. row ["BaseColumnName"] = row ["ColumnName"];
  361. switch ((TdsColumnType) schema ["ColumnType"]) {
  362. case TdsColumnType.Int1:
  363. case TdsColumnType.Int2:
  364. case TdsColumnType.Int4:
  365. case TdsColumnType.IntN:
  366. switch ((int) schema ["ColumnSize"]) {
  367. case 1:
  368. dataTypeNames.Add ("tinyint");
  369. row ["ProviderType"] = (int) SqlDbType.TinyInt;
  370. row ["DataType"] = typeof (byte);
  371. row ["IsLong"] = false;
  372. break;
  373. case 2:
  374. dataTypeNames.Add ("smallint");
  375. row ["ProviderType"] = (int) SqlDbType.SmallInt;
  376. row ["DataType"] = typeof (short);
  377. row ["IsLong"] = false;
  378. break;
  379. case 4:
  380. dataTypeNames.Add ("int");
  381. row ["ProviderType"] = (int) SqlDbType.Int;
  382. row ["DataType"] = typeof (int);
  383. row ["IsLong"] = false;
  384. break;
  385. case 8:
  386. dataTypeNames.Add ("bigint");
  387. row ["ProviderType"] = (int) SqlDbType.BigInt;
  388. row ["DataType"] = typeof (long);
  389. row ["IsLong"] = false;
  390. break;
  391. }
  392. break;
  393. case TdsColumnType.Real:
  394. case TdsColumnType.Float8:
  395. case TdsColumnType.FloatN:
  396. switch ((int) schema ["ColumnSize"]) {
  397. case 4:
  398. dataTypeNames.Add ("real");
  399. row ["ProviderType"] = (int) SqlDbType.Real;
  400. row ["DataType"] = typeof (float);
  401. row ["IsLong"] = false;
  402. break;
  403. case 8:
  404. dataTypeNames.Add ("float");
  405. row ["ProviderType"] = (int) SqlDbType.Float;
  406. row ["DataType"] = typeof (double);
  407. row ["IsLong"] = false;
  408. break;
  409. }
  410. break;
  411. case TdsColumnType.Image :
  412. dataTypeNames.Add ("image");
  413. row ["ProviderType"] = (int) SqlDbType.Image;
  414. row ["DataType"] = typeof (byte[]);
  415. row ["IsLong"] = true;
  416. break;
  417. case TdsColumnType.Text :
  418. dataTypeNames.Add ("text");
  419. row ["ProviderType"] = (int) SqlDbType.Text;
  420. row ["DataType"] = typeof (string);
  421. row ["IsLong"] = true;
  422. break;
  423. case TdsColumnType.UniqueIdentifier :
  424. dataTypeNames.Add ("uniqueidentifier");
  425. row ["ProviderType"] = (int) SqlDbType.UniqueIdentifier;
  426. row ["DataType"] = typeof (Guid);
  427. row ["IsLong"] = false;
  428. break;
  429. case TdsColumnType.VarBinary :
  430. case TdsColumnType.BigVarBinary :
  431. dataTypeNames.Add ("varbinary");
  432. row ["ProviderType"] = (int) SqlDbType.VarBinary;
  433. row ["DataType"] = typeof (byte[]);
  434. row ["IsLong"] = true;
  435. break;
  436. case TdsColumnType.VarChar :
  437. case TdsColumnType.BigVarChar :
  438. dataTypeNames.Add ("varchar");
  439. row ["ProviderType"] = (int) SqlDbType.VarChar;
  440. row ["DataType"] = typeof (string);
  441. row ["IsLong"] = false;
  442. break;
  443. case TdsColumnType.Binary :
  444. case TdsColumnType.BigBinary :
  445. dataTypeNames.Add ("binary");
  446. row ["ProviderType"] = (int) SqlDbType.Binary;
  447. row ["DataType"] = typeof (byte[]);
  448. row ["IsLong"] = true;
  449. break;
  450. case TdsColumnType.Char :
  451. case TdsColumnType.BigChar :
  452. dataTypeNames.Add ("char");
  453. row ["ProviderType"] = (int) SqlDbType.Char;
  454. row ["DataType"] = typeof (string);
  455. row ["IsLong"] = false;
  456. break;
  457. case TdsColumnType.Bit :
  458. case TdsColumnType.BitN :
  459. dataTypeNames.Add ("bit");
  460. row ["ProviderType"] = (int) SqlDbType.Bit;
  461. row ["DataType"] = typeof (bool);
  462. row ["IsLong"] = false;
  463. break;
  464. case TdsColumnType.DateTime4 :
  465. case TdsColumnType.DateTime :
  466. case TdsColumnType.DateTimeN :
  467. dataTypeNames.Add ("datetime");
  468. row ["ProviderType"] = (int) SqlDbType.DateTime;
  469. row ["DataType"] = typeof (DateTime);
  470. row ["IsLong"] = false;
  471. break;
  472. case TdsColumnType.Money :
  473. case TdsColumnType.MoneyN :
  474. case TdsColumnType.Money4 :
  475. dataTypeNames.Add ("money");
  476. row ["ProviderType"] = (int) SqlDbType.Money;
  477. row ["DataType"] = typeof (decimal);
  478. row ["IsLong"] = false;
  479. break;
  480. case TdsColumnType.NText :
  481. dataTypeNames.Add ("ntext");
  482. row ["ProviderType"] = (int) SqlDbType.NText;
  483. row ["DataType"] = typeof (string);
  484. row ["IsLong"] = true;
  485. break;
  486. case TdsColumnType.NVarChar :
  487. dataTypeNames.Add ("nvarchar");
  488. row ["ProviderType"] = (int) SqlDbType.NVarChar;
  489. row ["DataType"] = typeof (string);
  490. row ["IsLong"] = false;
  491. break;
  492. case TdsColumnType.Decimal :
  493. case TdsColumnType.Numeric :
  494. dataTypeNames.Add ("decimal");
  495. row ["ProviderType"] = (int) SqlDbType.Decimal;
  496. row ["DataType"] = typeof (decimal);
  497. row ["IsLong"] = false;
  498. break;
  499. case TdsColumnType.NChar :
  500. dataTypeNames.Add ("nchar");
  501. row ["ProviderType"] = (int) SqlDbType.NChar;
  502. row ["DataType"] = typeof (string);
  503. row ["IsLong"] = false;
  504. break;
  505. case TdsColumnType.SmallMoney :
  506. dataTypeNames.Add ("smallmoney");
  507. row ["ProviderType"] = (int) SqlDbType.SmallMoney;
  508. row ["DataType"] = typeof (decimal);
  509. row ["IsLong"] = false;
  510. break;
  511. default :
  512. dataTypeNames.Add ("variant");
  513. row ["ProviderType"] = (int) SqlDbType.Variant;
  514. row ["DataType"] = typeof (object);
  515. row ["IsLong"] = false;
  516. break;
  517. }
  518. schemaTable.Rows.Add (row);
  519. fieldCount += 1;
  520. }
  521. return schemaTable;
  522. }
  523. private static object GetSchemaValue (TdsDataColumn schema, object key)
  524. {
  525. if (schema.ContainsKey (key) && schema [key] != null)
  526. return schema [key];
  527. return DBNull.Value;
  528. }
  529. public SqlBinary GetSqlBinary (int i)
  530. {
  531. throw new NotImplementedException ();
  532. }
  533. public SqlBoolean GetSqlBoolean (int i)
  534. {
  535. object value = GetSqlValue (i);
  536. if (!(value is SqlBoolean))
  537. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  538. return (SqlBoolean) value;
  539. }
  540. public SqlByte GetSqlByte (int i)
  541. {
  542. object value = GetSqlValue (i);
  543. if (!(value is SqlByte))
  544. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  545. return (SqlByte) value;
  546. }
  547. public SqlDateTime GetSqlDateTime (int i)
  548. {
  549. object value = GetSqlValue (i);
  550. if (!(value is SqlDateTime))
  551. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  552. return (SqlDateTime) value;
  553. }
  554. public SqlDecimal GetSqlDecimal (int i)
  555. {
  556. object value = GetSqlValue (i);
  557. if (!(value is SqlDecimal))
  558. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  559. return (SqlDecimal) value;
  560. }
  561. public SqlDouble GetSqlDouble (int i)
  562. {
  563. object value = GetSqlValue (i);
  564. if (!(value is SqlDouble))
  565. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  566. return (SqlDouble) value;
  567. }
  568. public SqlGuid GetSqlGuid (int i)
  569. {
  570. object value = GetSqlValue (i);
  571. if (!(value is SqlGuid))
  572. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  573. return (SqlGuid) value;
  574. }
  575. public SqlInt16 GetSqlInt16 (int i)
  576. {
  577. object value = GetSqlValue (i);
  578. if (!(value is SqlInt16))
  579. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  580. return (SqlInt16) value;
  581. }
  582. public SqlInt32 GetSqlInt32 (int i)
  583. {
  584. object value = GetSqlValue (i);
  585. if (!(value is SqlInt32))
  586. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  587. return (SqlInt32) value;
  588. }
  589. public SqlInt64 GetSqlInt64 (int i)
  590. {
  591. object value = GetSqlValue (i);
  592. if (!(value is SqlInt64))
  593. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  594. return (SqlInt64) value;
  595. }
  596. public SqlMoney GetSqlMoney (int i)
  597. {
  598. object value = GetSqlValue (i);
  599. if (!(value is SqlMoney))
  600. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  601. return (SqlMoney) value;
  602. }
  603. public SqlSingle GetSqlSingle (int i)
  604. {
  605. object value = GetSqlValue (i);
  606. if (!(value is SqlSingle))
  607. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  608. return (SqlSingle) value;
  609. }
  610. public SqlString GetSqlString (int i)
  611. {
  612. object value = GetSqlValue (i);
  613. if (!(value is SqlString))
  614. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  615. return (SqlString) value;
  616. }
  617. public object GetSqlValue (int i)
  618. {
  619. SqlDbType type = (SqlDbType) (schemaTable.Rows [i]["ProviderType"]);
  620. object value = GetValue (i);
  621. switch (type) {
  622. case SqlDbType.BigInt:
  623. if (value == DBNull.Value)
  624. return SqlInt64.Null;
  625. return (SqlInt64) ((long) value);
  626. case SqlDbType.Binary:
  627. case SqlDbType.Image:
  628. case SqlDbType.VarBinary:
  629. case SqlDbType.Timestamp:
  630. if (value == DBNull.Value)
  631. return SqlBinary.Null;
  632. return (SqlBinary) ((byte[]) value);
  633. case SqlDbType.Bit:
  634. if (value == DBNull.Value)
  635. return SqlBoolean.Null;
  636. return (SqlBoolean) ((bool) value);
  637. case SqlDbType.Char:
  638. case SqlDbType.NChar:
  639. case SqlDbType.NText:
  640. case SqlDbType.NVarChar:
  641. case SqlDbType.Text:
  642. case SqlDbType.VarChar:
  643. if (value == DBNull.Value)
  644. return SqlString.Null;
  645. return (SqlString) ((string) value);
  646. case SqlDbType.DateTime:
  647. case SqlDbType.SmallDateTime:
  648. if (value == DBNull.Value)
  649. return SqlDateTime.Null;
  650. return (SqlDateTime) ((DateTime) value);
  651. case SqlDbType.Decimal:
  652. if (value == DBNull.Value)
  653. return SqlDecimal.Null;
  654. if (value is TdsBigDecimal)
  655. return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
  656. return (SqlDecimal) ((decimal) value);
  657. case SqlDbType.Float:
  658. if (value == DBNull.Value)
  659. return SqlDouble.Null;
  660. return (SqlDouble) ((double) value);
  661. case SqlDbType.Int:
  662. if (value == DBNull.Value)
  663. return SqlInt32.Null;
  664. return (SqlInt32) ((int) value);
  665. case SqlDbType.Money:
  666. case SqlDbType.SmallMoney:
  667. if (value == DBNull.Value)
  668. return SqlMoney.Null;
  669. return (SqlMoney) ((decimal) value);
  670. case SqlDbType.Real:
  671. if (value == DBNull.Value)
  672. return SqlSingle.Null;
  673. return (SqlSingle) ((float) value);
  674. case SqlDbType.UniqueIdentifier:
  675. if (value == DBNull.Value)
  676. return SqlGuid.Null;
  677. return (SqlGuid) ((Guid) value);
  678. case SqlDbType.SmallInt:
  679. if (value == DBNull.Value)
  680. return SqlInt16.Null;
  681. return (SqlInt16) ((short) value);
  682. case SqlDbType.TinyInt:
  683. if (value == DBNull.Value)
  684. return SqlByte.Null;
  685. return (SqlByte) ((byte) value);
  686. }
  687. throw new InvalidOperationException ("The type of this column is unknown.");
  688. }
  689. public int GetSqlValues (object[] values)
  690. {
  691. int count = 0;
  692. int columnCount = schemaTable.Rows.Count;
  693. int arrayCount = values.Length;
  694. if (arrayCount > columnCount)
  695. count = columnCount;
  696. else
  697. count = arrayCount;
  698. for (int i = 0; i < count; i += 1)
  699. values [i] = GetSqlValue (i);
  700. return count;
  701. }
  702. public string GetString (int i)
  703. {
  704. object value = GetValue (i);
  705. if (!(value is string)) {
  706. if (value is DBNull) throw new SqlNullValueException ();
  707. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  708. }
  709. return (string) value;
  710. }
  711. public object GetValue (int i)
  712. {
  713. return command.Tds.ColumnValues [i];
  714. }
  715. public int GetValues (object[] values)
  716. {
  717. int len = values.Length;
  718. int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
  719. // If a four-byte decimal is stored, then we can't convert to
  720. // a native type. Throw an OverflowException.
  721. if (bigDecimalIndex >= 0 && bigDecimalIndex < len)
  722. throw new OverflowException ();
  723. command.Tds.ColumnValues.CopyTo (0, values, 0, len);
  724. return (len > FieldCount ? len : FieldCount);
  725. }
  726. void IDisposable.Dispose ()
  727. {
  728. Dispose (true);
  729. GC.SuppressFinalize (this);
  730. }
  731. IEnumerator IEnumerable.GetEnumerator ()
  732. {
  733. return new DbEnumerator (this);
  734. }
  735. public bool IsDBNull (int i)
  736. {
  737. return GetValue (i) == DBNull.Value;
  738. }
  739. public bool NextResult ()
  740. {
  741. if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
  742. return false;
  743. schemaTable.Rows.Clear ();
  744. moreResults = command.Tds.NextResult ();
  745. if (!moreResults)
  746. command.GetOutputParameters ();
  747. GetSchemaTable ();
  748. rowsRead = 0;
  749. resultsRead += 1;
  750. return moreResults;
  751. }
  752. public bool Read ()
  753. {
  754. if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
  755. return false;
  756. if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
  757. return false;
  758. if (!moreResults)
  759. return false;
  760. if ((haveRead) && (!readResultUsed))
  761. {
  762. readResultUsed = true;
  763. return true;
  764. }
  765. return (ReadRecord ());
  766. }
  767. internal bool ReadRecord ()
  768. {
  769. bool result = command.Tds.NextRow ();
  770. rowsRead += 1;
  771. return result;
  772. }
  773. #endregion // Methods
  774. }
  775. }