SqlDataReader.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  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.IO;
  38. using System.Text;
  39. using System.Collections;
  40. using System.ComponentModel;
  41. using System.Data;
  42. using System.Data.Common;
  43. using System.Data.SqlTypes;
  44. using System.Xml;
  45. namespace System.Data.SqlClient
  46. {
  47. #if NET_2_0
  48. public class SqlDataReader : DbDataReader, IDataReader, IDisposable, IDataRecord
  49. #else
  50. public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
  51. #endif // NET_2_0
  52. {
  53. #region Fields
  54. SqlCommand command;
  55. ArrayList dataTypeNames;
  56. bool disposed;
  57. bool isClosed;
  58. bool moreResults;
  59. int resultsRead;
  60. int rowsRead;
  61. DataTable schemaTable;
  62. bool haveRead;
  63. bool readResult;
  64. bool readResultUsed;
  65. #if NET_2_0
  66. int visibleFieldCount;
  67. #endif
  68. #endregion // Fields
  69. const int COLUMN_NAME_IDX = 0;
  70. const int COLUMN_ORDINAL_IDX = 1;
  71. const int COLUMN_SIZE_IDX = 2;
  72. const int NUMERIC_PRECISION_IDX = 3;
  73. const int NUMERIC_SCALE_IDX = 4;
  74. const int IS_UNIQUE_IDX = 5;
  75. const int IS_KEY_IDX = 6;
  76. const int BASE_SERVER_NAME_IDX = 7;
  77. const int BASE_CATALOG_NAME_IDX = 8;
  78. const int BASE_COLUMN_NAME_IDX = 9;
  79. const int BASE_SCHEMA_NAME_IDX = 10;
  80. const int BASE_TABLE_NAME_IDX = 11;
  81. const int DATA_TYPE_IDX = 12;
  82. const int ALLOW_DBNULL_IDX = 13;
  83. const int PROVIDER_TYPE_IDX = 14;
  84. const int IS_ALIASED_IDX = 15;
  85. const int IS_EXPRESSION_IDX = 16;
  86. const int IS_IDENTITY_IDX = 17;
  87. const int IS_AUTO_INCREMENT_IDX = 18;
  88. const int IS_ROW_VERSION_IDX = 19;
  89. const int IS_HIDDEN_IDX = 20;
  90. const int IS_LONG_IDX = 21;
  91. const int IS_READ_ONLY_IDX = 22;
  92. #region Constructors
  93. internal SqlDataReader (SqlCommand command)
  94. {
  95. readResult = false;
  96. haveRead = false;
  97. readResultUsed = false;
  98. this.command = command;
  99. resultsRead = 0;
  100. isClosed = false;
  101. command.Tds.RecordsAffected = -1;
  102. #if NET_2_0
  103. visibleFieldCount = 0;
  104. #endif
  105. NextResult ();
  106. }
  107. #endregion // Constructors
  108. #region Properties
  109. public
  110. #if NET_2_0
  111. override
  112. #endif // NET_2_0
  113. int Depth {
  114. get { return 0; }
  115. }
  116. public
  117. #if NET_2_0
  118. override
  119. #endif // NET_2_0
  120. int FieldCount {
  121. get { return command.Tds.Columns.Count; }
  122. }
  123. public
  124. #if NET_2_0
  125. override
  126. #endif // NET_2_0
  127. bool IsClosed {
  128. get { return isClosed; }
  129. }
  130. public
  131. #if NET_2_0
  132. override
  133. #endif // NET_2_0
  134. object this [int i] {
  135. get { return GetValue (i); }
  136. }
  137. public
  138. #if NET_2_0
  139. override
  140. #endif // NET_2_0
  141. object this [string name] {
  142. get { return GetValue (GetOrdinal (name)); }
  143. }
  144. public
  145. #if NET_2_0
  146. override
  147. #endif // NET_2_0
  148. int RecordsAffected {
  149. get {
  150. return command.Tds.RecordsAffected;
  151. }
  152. }
  153. public
  154. #if NET_2_0
  155. override
  156. #endif // NET_2_0
  157. bool HasRows {
  158. get {
  159. if (haveRead)
  160. return readResult;
  161. haveRead = true;
  162. readResult = ReadRecord ();
  163. return readResult;
  164. }
  165. }
  166. #if NET_2_0
  167. public override int VisibleFieldCount {
  168. get { return visibleFieldCount; }
  169. }
  170. protected SqlConnection Connection {
  171. get { return command.Connection; }
  172. }
  173. protected bool IsCommandBehavior (CommandBehavior condition) {
  174. return condition == command.CommandBehavior;
  175. }
  176. #endif
  177. #endregion // Properties
  178. #region Methods
  179. public
  180. #if NET_2_0
  181. override
  182. #endif // NET_2_0
  183. void Close ()
  184. {
  185. if (IsClosed)
  186. return;
  187. // skip to end & read output parameters.
  188. while (NextResult ())
  189. ;
  190. isClosed = true;
  191. command.CloseDataReader ();
  192. }
  193. private static DataTable ConstructSchemaTable ()
  194. {
  195. Type booleanType = typeof (bool);
  196. Type stringType = typeof (string);
  197. Type intType = typeof (int);
  198. Type typeType = typeof (Type);
  199. Type shortType = typeof (short);
  200. DataTable schemaTable = new DataTable ("SchemaTable");
  201. schemaTable.Columns.Add ("ColumnName", stringType);
  202. schemaTable.Columns.Add ("ColumnOrdinal", intType);
  203. schemaTable.Columns.Add ("ColumnSize", intType);
  204. schemaTable.Columns.Add ("NumericPrecision", shortType);
  205. schemaTable.Columns.Add ("NumericScale", shortType);
  206. schemaTable.Columns.Add ("IsUnique", booleanType);
  207. schemaTable.Columns.Add ("IsKey", booleanType);
  208. schemaTable.Columns.Add ("BaseServerName", stringType);
  209. schemaTable.Columns.Add ("BaseCatalogName", stringType);
  210. schemaTable.Columns.Add ("BaseColumnName", stringType);
  211. schemaTable.Columns.Add ("BaseSchemaName", stringType);
  212. schemaTable.Columns.Add ("BaseTableName", stringType);
  213. schemaTable.Columns.Add ("DataType", typeType);
  214. schemaTable.Columns.Add ("AllowDBNull", booleanType);
  215. schemaTable.Columns.Add ("ProviderType", intType);
  216. schemaTable.Columns.Add ("IsAliased", booleanType);
  217. schemaTable.Columns.Add ("IsExpression", booleanType);
  218. schemaTable.Columns.Add ("IsIdentity", booleanType);
  219. schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
  220. schemaTable.Columns.Add ("IsRowVersion", booleanType);
  221. schemaTable.Columns.Add ("IsHidden", booleanType);
  222. schemaTable.Columns.Add ("IsLong", booleanType);
  223. schemaTable.Columns.Add ("IsReadOnly", booleanType);
  224. return schemaTable;
  225. }
  226. private void GetSchemaRowTypeName (TdsColumnType ctype, int csize, out string typeName)
  227. {
  228. int dbType;
  229. bool isLong;
  230. Type fieldType;
  231. GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
  232. }
  233. private void GetSchemaRowFieldType (TdsColumnType ctype, int csize, out Type fieldType)
  234. {
  235. int dbType;
  236. bool isLong;
  237. string typeName;
  238. GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
  239. }
  240. private void GetSchemaRowDbType (TdsColumnType ctype, int csize, out int dbType)
  241. {
  242. Type fieldType;
  243. bool isLong;
  244. string typeName;
  245. GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
  246. }
  247. private void GetSchemaRowType (TdsColumnType ctype, int csize,
  248. out int dbType, out Type fieldType,
  249. out bool isLong, out string typeName)
  250. {
  251. dbType = -1;
  252. typeName = string.Empty;
  253. isLong = false;
  254. fieldType = typeof (Type);
  255. switch (ctype) {
  256. case TdsColumnType.Int1:
  257. case TdsColumnType.Int2:
  258. case TdsColumnType.Int4:
  259. case TdsColumnType.IntN:
  260. switch (csize) {
  261. case 1:
  262. typeName = "tinyint";
  263. dbType = (int) SqlDbType.TinyInt;
  264. fieldType = typeof (byte);
  265. isLong = false;
  266. break;
  267. case 2:
  268. typeName = "smallint";
  269. dbType = (int) SqlDbType.SmallInt;
  270. fieldType = typeof (short);
  271. isLong = false;
  272. break;
  273. case 4:
  274. typeName = "int";
  275. dbType = (int) SqlDbType.Int;
  276. fieldType = typeof (int);
  277. isLong = false;
  278. break;
  279. case 8:
  280. typeName = "bigint";
  281. dbType = (int) SqlDbType.BigInt;
  282. fieldType = typeof (long);
  283. isLong = false;
  284. break;
  285. }
  286. break;
  287. case TdsColumnType.Real:
  288. case TdsColumnType.Float8:
  289. case TdsColumnType.FloatN:
  290. switch (csize) {
  291. case 4:
  292. typeName = "real";
  293. dbType = (int) SqlDbType.Real;
  294. fieldType = typeof (float);
  295. isLong = false;
  296. break;
  297. case 8:
  298. typeName = "float";
  299. dbType = (int) SqlDbType.Float;
  300. fieldType = typeof (double);
  301. isLong = false;
  302. break;
  303. }
  304. break;
  305. case TdsColumnType.Image :
  306. typeName = "image";
  307. dbType = (int) SqlDbType.Image;
  308. fieldType = typeof (byte[]);
  309. isLong = true;
  310. break;
  311. case TdsColumnType.Text :
  312. typeName = "text";
  313. dbType = (int) SqlDbType.Text;
  314. fieldType = typeof (string);
  315. isLong = true;
  316. break;
  317. case TdsColumnType.UniqueIdentifier :
  318. typeName = "uniqueidentifier";
  319. dbType = (int) SqlDbType.UniqueIdentifier;
  320. fieldType = typeof (Guid);
  321. isLong = false;
  322. break;
  323. case TdsColumnType.VarBinary :
  324. case TdsColumnType.BigVarBinary :
  325. typeName = "varbinary";
  326. dbType = (int) SqlDbType.VarBinary;
  327. fieldType = typeof (byte[]);
  328. isLong = true;
  329. break;
  330. case TdsColumnType.VarChar :
  331. case TdsColumnType.BigVarChar :
  332. typeName = "varchar";
  333. dbType = (int) SqlDbType.VarChar;
  334. fieldType = typeof (string);
  335. isLong = false;
  336. break;
  337. case TdsColumnType.Binary :
  338. case TdsColumnType.BigBinary :
  339. typeName = "binary";
  340. dbType = (int) SqlDbType.Binary;
  341. fieldType = typeof (byte[]);
  342. isLong = true;
  343. break;
  344. case TdsColumnType.Char :
  345. case TdsColumnType.BigChar :
  346. typeName = "char";
  347. dbType = (int) SqlDbType.Char;
  348. fieldType = typeof (string);
  349. isLong = false;
  350. break;
  351. case TdsColumnType.Bit :
  352. case TdsColumnType.BitN :
  353. typeName = "bit";
  354. dbType = (int) SqlDbType.Bit;
  355. fieldType = typeof (bool);
  356. isLong = false;
  357. break;
  358. case TdsColumnType.DateTime4 :
  359. case TdsColumnType.DateTime :
  360. case TdsColumnType.DateTimeN :
  361. typeName = "datetime";
  362. dbType = (int) SqlDbType.DateTime;
  363. fieldType = typeof (DateTime);
  364. isLong = false;
  365. break;
  366. case TdsColumnType.Money :
  367. case TdsColumnType.MoneyN :
  368. case TdsColumnType.Money4 :
  369. typeName = "money";
  370. dbType = (int) SqlDbType.Money;
  371. fieldType = typeof (decimal);
  372. isLong = false;
  373. break;
  374. case TdsColumnType.NText :
  375. typeName = "ntext";
  376. dbType = (int) SqlDbType.NText;
  377. fieldType = typeof (string);
  378. isLong = true;
  379. break;
  380. case TdsColumnType.NVarChar :
  381. typeName = "nvarchar";
  382. dbType = (int) SqlDbType.NVarChar;
  383. fieldType = typeof (string);
  384. isLong = false;
  385. break;
  386. case TdsColumnType.Decimal :
  387. case TdsColumnType.Numeric :
  388. typeName = "decimal";
  389. dbType = (int) SqlDbType.Decimal;
  390. fieldType = typeof (decimal);
  391. isLong = false;
  392. break;
  393. case TdsColumnType.NChar :
  394. typeName = "nchar";
  395. dbType = (int) SqlDbType.NChar;
  396. fieldType = typeof (string);
  397. isLong = false;
  398. break;
  399. case TdsColumnType.SmallMoney :
  400. typeName = "smallmoney";
  401. dbType = (int) SqlDbType.SmallMoney;
  402. fieldType = typeof (decimal);
  403. isLong = false;
  404. break;
  405. default :
  406. typeName = "variant";
  407. dbType = (int) SqlDbType.Variant;
  408. fieldType = typeof (object);
  409. isLong = false;
  410. break;
  411. }
  412. }
  413. #if NET_2_0
  414. new
  415. #endif
  416. void Dispose (bool disposing)
  417. {
  418. if (!disposed) {
  419. if (disposing) {
  420. if (schemaTable != null)
  421. schemaTable.Dispose ();
  422. Close ();
  423. command = null;
  424. }
  425. disposed = true;
  426. }
  427. }
  428. public
  429. #if NET_2_0
  430. override
  431. #endif // NET_2_0
  432. bool GetBoolean (int i)
  433. {
  434. object value = GetValue (i);
  435. if (!(value is bool)) {
  436. if (value is DBNull) throw new SqlNullValueException ();
  437. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  438. }
  439. return (bool) value;
  440. }
  441. public
  442. #if NET_2_0
  443. override
  444. #endif // NET_2_0
  445. byte GetByte (int i)
  446. {
  447. object value = GetValue (i);
  448. if (!(value is byte)) {
  449. if (value is DBNull) throw new SqlNullValueException ();
  450. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  451. }
  452. return (byte) value;
  453. }
  454. public
  455. #if NET_2_0
  456. override
  457. #endif // NET_2_0
  458. long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
  459. {
  460. if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
  461. try {
  462. long len = ((Tds)command.Tds).GetSequentialColumnValue (i, dataIndex, buffer, bufferIndex, length);
  463. if (len == -1)
  464. throw new InvalidCastException ("Invalid attempt to GetBytes on column "
  465. + "'" + command.Tds.Columns[i]["ColumnName"] +
  466. "'." + "The GetBytes function"
  467. + " can only be used on columns of type Text, NText, or Image");
  468. return len;
  469. } catch (TdsInternalException ex) {
  470. command.Connection.Close ();
  471. throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
  472. }
  473. }
  474. object value = GetValue (i);
  475. if (!(value is byte [])) {
  476. if (value is DBNull) throw new SqlNullValueException ();
  477. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  478. }
  479. if ( buffer == null )
  480. return ((byte []) value).Length; // Return length of data
  481. // Copy data into buffer
  482. int availLen = (int) ( ( (byte []) value).Length - dataIndex);
  483. if (availLen < length)
  484. length = availLen;
  485. Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
  486. return length; // return actual read count
  487. }
  488. [EditorBrowsableAttribute (EditorBrowsableState.Never)]
  489. public
  490. #if NET_2_0
  491. override
  492. #endif // NET_2_0
  493. char GetChar (int i)
  494. {
  495. object value = GetValue (i);
  496. if (!(value is char)) {
  497. if (value is DBNull) throw new SqlNullValueException ();
  498. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  499. }
  500. return (char) value;
  501. }
  502. public
  503. #if NET_2_0
  504. override
  505. #endif // NET_2_0
  506. long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
  507. {
  508. if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
  509. Encoding encoding = null;
  510. byte mul = 1;
  511. TdsColumnType colType = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
  512. switch (colType) {
  513. case TdsColumnType.Text :
  514. case TdsColumnType.VarChar:
  515. case TdsColumnType.Char:
  516. case TdsColumnType.BigVarChar:
  517. encoding = Encoding.ASCII;
  518. break;
  519. case TdsColumnType.NText :
  520. case TdsColumnType.NVarChar:
  521. case TdsColumnType.NChar:
  522. encoding = Encoding.Unicode;
  523. mul = 2;
  524. break;
  525. default :
  526. return -1;
  527. }
  528. long count = 0;
  529. if (buffer == null) {
  530. count = GetBytes (i,0,(byte[]) null,0,0);
  531. return (count/mul);
  532. }
  533. length *= mul;
  534. byte[] arr = new byte [length];
  535. count = GetBytes (i, dataIndex, arr, 0, length);
  536. if (count == -1)
  537. throw new InvalidCastException ("Specified cast is not valid");
  538. Char[] val = encoding.GetChars (arr, 0, (int)count);
  539. val.CopyTo (buffer, bufferIndex);
  540. return val.Length;
  541. }
  542. char [] valueBuffer;
  543. object value = GetValue (i);
  544. if (value is char[])
  545. valueBuffer = (char[])value;
  546. else if (value is string)
  547. valueBuffer = ((string)value).ToCharArray();
  548. else {
  549. if (value is DBNull) throw new SqlNullValueException ();
  550. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  551. }
  552. if ( buffer == null ) {
  553. // Return length of data
  554. return valueBuffer.Length;
  555. }
  556. else {
  557. // Copy data into buffer
  558. Array.Copy (valueBuffer, (int) dataIndex, buffer, bufferIndex, length);
  559. return valueBuffer.Length - dataIndex;
  560. }
  561. }
  562. #if !NET_2_0
  563. [EditorBrowsableAttribute (EditorBrowsableState.Never)]
  564. public new IDataReader GetData (int i)
  565. {
  566. return ((IDataReader) this [i]);
  567. }
  568. #endif
  569. public
  570. #if NET_2_0
  571. override
  572. #endif // NET_2_0
  573. string GetDataTypeName (int i)
  574. {
  575. TdsColumnType ctype;
  576. string datatypeName;
  577. int csize;
  578. if (i < 0 || i >= command.Tds.Columns.Count)
  579. throw new IndexOutOfRangeException ();
  580. #if NET_2_0
  581. ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
  582. csize = (int) command.Tds.Columns[i].ColumnSize;
  583. #else
  584. ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
  585. csize = (int) command.Tds.Columns[i]["ColumnSize"];
  586. #endif
  587. GetSchemaRowTypeName (ctype, csize, out datatypeName);
  588. return datatypeName;
  589. }
  590. public
  591. #if NET_2_0
  592. override
  593. #endif // NET_2_0
  594. DateTime GetDateTime (int i)
  595. {
  596. object value = GetValue (i);
  597. if (!(value is DateTime)) {
  598. if (value is DBNull) throw new SqlNullValueException ();
  599. else throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  600. }
  601. return (DateTime) value;
  602. }
  603. public
  604. #if NET_2_0
  605. override
  606. #endif // NET_2_0
  607. decimal GetDecimal (int i)
  608. {
  609. object value = GetValue (i);
  610. if (!(value is decimal)) {
  611. if (value is DBNull) throw new SqlNullValueException ();
  612. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  613. }
  614. return (decimal) value;
  615. }
  616. public
  617. #if NET_2_0
  618. override
  619. #endif // NET_2_0
  620. double GetDouble (int i)
  621. {
  622. object value = GetValue (i);
  623. if (!(value is double)) {
  624. if (value is DBNull) throw new SqlNullValueException ();
  625. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  626. }
  627. return (double) value;
  628. }
  629. public
  630. #if NET_2_0
  631. override
  632. #endif // NET_2_0
  633. Type GetFieldType (int i)
  634. {
  635. TdsColumnType ctype;
  636. Type fieldType;
  637. int csize;
  638. if (i < 0 || i >= command.Tds.Columns.Count)
  639. throw new IndexOutOfRangeException ();
  640. #if NET_2_0
  641. ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
  642. csize = (int) command.Tds.Columns[i].ColumnSize;
  643. #else
  644. ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
  645. csize = (int) command.Tds.Columns[i]["ColumnSize"];
  646. #endif
  647. GetSchemaRowFieldType (ctype, csize, out fieldType);
  648. return fieldType;
  649. }
  650. public
  651. #if NET_2_0
  652. override
  653. #endif // NET_2_0
  654. float GetFloat (int i)
  655. {
  656. object value = GetValue (i);
  657. if (!(value is float)) {
  658. if (value is DBNull) throw new SqlNullValueException ();
  659. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  660. }
  661. return (float) value;
  662. }
  663. public
  664. #if NET_2_0
  665. override
  666. #endif // NET_2_0
  667. Guid GetGuid (int i)
  668. {
  669. object value = GetValue (i);
  670. if (!(value is Guid)) {
  671. if (value is DBNull) throw new SqlNullValueException ();
  672. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  673. }
  674. return (Guid) value;
  675. }
  676. public
  677. #if NET_2_0
  678. override
  679. #endif // NET_2_0
  680. short GetInt16 (int i)
  681. {
  682. object value = GetValue (i);
  683. if (!(value is short)) {
  684. if (value is DBNull) throw new SqlNullValueException ();
  685. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  686. }
  687. return (short) value;
  688. }
  689. public
  690. #if NET_2_0
  691. override
  692. #endif // NET_2_0
  693. int GetInt32 (int i)
  694. {
  695. object value = GetValue (i);
  696. if (!(value is int)) {
  697. if (value is DBNull) throw new SqlNullValueException ();
  698. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  699. }
  700. return (int) value;
  701. }
  702. public
  703. #if NET_2_0
  704. override
  705. #endif // NET_2_0
  706. long GetInt64 (int i)
  707. {
  708. object value = GetValue (i);
  709. if (!(value is long)) {
  710. if (value is DBNull) throw new SqlNullValueException ();
  711. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  712. }
  713. return (long) value;
  714. }
  715. public
  716. #if NET_2_0
  717. override
  718. #endif // NET_2_0
  719. string GetName (int i)
  720. {
  721. if (i < 0 || i >= command.Tds.Columns.Count)
  722. throw new IndexOutOfRangeException ();
  723. #if NET_2_0
  724. return (string) command.Tds.Columns[i].ColumnName;
  725. #else
  726. return (string) command.Tds.Columns[i]["ColumnName"];
  727. #endif
  728. }
  729. public
  730. #if NET_2_0
  731. override
  732. #endif // NET_2_0
  733. int GetOrdinal (string name)
  734. {
  735. string colName;
  736. foreach (TdsDataColumn schema in command.Tds.Columns) {
  737. #if NET_2_0
  738. colName = schema.ColumnName;
  739. if (colName.Equals (name) || String.Compare (colName, name, true) == 0)
  740. return (int) schema.ColumnOrdinal;
  741. #else
  742. colName = (string) schema["ColumnName"];
  743. if (colName.Equals (name) || String.Compare (colName, name, true) == 0)
  744. return (int) schema["ColumnOrdinal"];
  745. #endif
  746. }
  747. throw new IndexOutOfRangeException ();
  748. }
  749. public
  750. #if NET_2_0
  751. override
  752. #endif // NET_2_0
  753. DataTable GetSchemaTable ()
  754. {
  755. ValidateState ();
  756. if (schemaTable == null)
  757. schemaTable = ConstructSchemaTable ();
  758. if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
  759. return schemaTable;
  760. if (!moreResults)
  761. return null;
  762. dataTypeNames = new ArrayList (command.Tds.Columns.Count);
  763. foreach (TdsDataColumn schema in command.Tds.Columns) {
  764. DataRow row = schemaTable.NewRow ();
  765. #if NET_2_0
  766. row [COLUMN_NAME_IDX] = GetSchemaValue (schema.ColumnName);
  767. row [COLUMN_ORDINAL_IDX] = GetSchemaValue (schema.ColumnOrdinal);
  768. row [IS_UNIQUE_IDX] = GetSchemaValue (schema.IsUnique);
  769. row [IS_AUTO_INCREMENT_IDX] = GetSchemaValue (schema.IsAutoIncrement);
  770. row [IS_ROW_VERSION_IDX] = GetSchemaValue (schema.IsRowVersion);
  771. row [IS_HIDDEN_IDX] = GetSchemaValue (schema.IsHidden);
  772. row [IS_IDENTITY_IDX] = GetSchemaValue (schema.IsIdentity);
  773. row [COLUMN_SIZE_IDX] = GetSchemaValue (schema.ColumnSize);
  774. row [NUMERIC_PRECISION_IDX] = GetSchemaValue (schema.NumericPrecision);
  775. row [NUMERIC_SCALE_IDX] = GetSchemaValue (schema.NumericScale);
  776. row [IS_KEY_IDX] = GetSchemaValue (schema.IsKey);
  777. row [IS_ALIASED_IDX] = GetSchemaValue (schema.IsAliased);
  778. row [IS_EXPRESSION_IDX] = GetSchemaValue (schema.IsExpression);
  779. row [IS_READ_ONLY_IDX] = GetSchemaValue (schema.IsReadOnly);
  780. row [BASE_SERVER_NAME_IDX] = GetSchemaValue (schema.BaseServerName);
  781. row [BASE_CATALOG_NAME_IDX] = GetSchemaValue (schema.BaseCatalogName);
  782. row [BASE_COLUMN_NAME_IDX] = GetSchemaValue (schema.BaseColumnName);
  783. row [BASE_SCHEMA_NAME_IDX] = GetSchemaValue (schema.BaseSchemaName);
  784. row [BASE_TABLE_NAME_IDX] = GetSchemaValue (schema.BaseTableName);
  785. row [ALLOW_DBNULL_IDX] = GetSchemaValue (schema.AllowDBNull);
  786. #else
  787. row ["ColumnName"] = GetSchemaValue (schema, "ColumnName");
  788. row ["ColumnOrdinal"] = GetSchemaValue (schema, "ColumnOrdinal");
  789. row ["IsUnique"] = GetSchemaValue (schema, "IsUnique");
  790. row ["IsAutoIncrement"] = GetSchemaValue (schema, "IsAutoIncrement");
  791. row ["IsRowVersion"] = GetSchemaValue (schema, "IsRowVersion");
  792. row ["IsHidden"] = GetSchemaValue (schema, "IsHidden");
  793. row ["IsIdentity"] = GetSchemaValue (schema, "IsIdentity");
  794. row ["ColumnSize"] = GetSchemaValue (schema, "ColumnSize");
  795. row ["NumericPrecision"] = GetSchemaValue (schema, "NumericPrecision");
  796. row ["NumericScale"] = GetSchemaValue (schema, "NumericScale");
  797. row ["IsKey"] = GetSchemaValue (schema, "IsKey");
  798. row ["IsAliased"] = GetSchemaValue (schema, "IsAliased");
  799. row ["IsExpression"] = GetSchemaValue (schema, "IsExpression");
  800. row ["IsReadOnly"] = GetSchemaValue (schema, "IsReadOnly");
  801. row ["BaseServerName"] = GetSchemaValue (schema, "BaseServerName");
  802. row ["BaseCatalogName"] = GetSchemaValue (schema, "BaseCatalogName");
  803. row ["BaseColumnName"] = GetSchemaValue (schema, "BaseColumnName");
  804. row ["BaseSchemaName"] = GetSchemaValue (schema, "BaseSchemaName");
  805. row ["BaseTableName"] = GetSchemaValue (schema, "BaseTableName");
  806. row ["AllowDBNull"] = GetSchemaValue (schema, "AllowDBNull");
  807. #endif
  808. // We don't always get the base column name.
  809. if (row [BASE_COLUMN_NAME_IDX] == DBNull.Value)
  810. row [BASE_COLUMN_NAME_IDX] = row [COLUMN_NAME_IDX];
  811. TdsColumnType ctype;
  812. int csize, dbType;
  813. Type fieldType;
  814. bool isLong;
  815. string typeName;
  816. #if NET_2_0
  817. ctype = (TdsColumnType) schema.ColumnType;
  818. csize = (int) schema.ColumnSize;
  819. #else
  820. ctype = (TdsColumnType) schema ["ColumnType"];
  821. csize = (int) schema ["ColumnSize"];
  822. #endif
  823. GetSchemaRowType (ctype, csize, out dbType,
  824. out fieldType, out isLong, out typeName);
  825. dataTypeNames.Add (typeName);
  826. row [PROVIDER_TYPE_IDX] = dbType;
  827. row [DATA_TYPE_IDX] = fieldType;
  828. row [IS_LONG_IDX] = isLong;
  829. #if NET_2_0
  830. if ((bool)row [IS_HIDDEN_IDX] == false)
  831. visibleFieldCount += 1;
  832. #endif
  833. schemaTable.Rows.Add (row);
  834. }
  835. return schemaTable;
  836. }
  837. private static object GetSchemaValue (TdsDataColumn schema, string key)
  838. {
  839. object val = schema [key];
  840. if (val != null)
  841. return val;
  842. else
  843. return DBNull.Value;
  844. }
  845. #if NET_2_0
  846. static object GetSchemaValue (object value)
  847. {
  848. if (value == null)
  849. return DBNull.Value;
  850. return value;
  851. }
  852. #endif
  853. public
  854. #if NET_2_0
  855. virtual
  856. #endif
  857. SqlBinary GetSqlBinary (int i)
  858. {
  859. object value = GetSqlValue (i);
  860. if (!(value is SqlBinary))
  861. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  862. return (SqlBinary) value;
  863. }
  864. public
  865. #if NET_2_0
  866. virtual
  867. #endif
  868. SqlBoolean GetSqlBoolean (int i)
  869. {
  870. object value = GetSqlValue (i);
  871. if (!(value is SqlBoolean))
  872. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  873. return (SqlBoolean) value;
  874. }
  875. public
  876. #if NET_2_0
  877. virtual
  878. #endif
  879. SqlByte GetSqlByte (int i)
  880. {
  881. object value = GetSqlValue (i);
  882. if (!(value is SqlByte))
  883. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  884. return (SqlByte) value;
  885. }
  886. public
  887. #if NET_2_0
  888. virtual
  889. #endif
  890. SqlDateTime GetSqlDateTime (int i)
  891. {
  892. object value = GetSqlValue (i);
  893. if (!(value is SqlDateTime))
  894. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  895. return (SqlDateTime) value;
  896. }
  897. public
  898. #if NET_2_0
  899. virtual
  900. #endif
  901. SqlDecimal GetSqlDecimal (int i)
  902. {
  903. object value = GetSqlValue (i);
  904. if (!(value is SqlDecimal))
  905. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  906. return (SqlDecimal) value;
  907. }
  908. public
  909. #if NET_2_0
  910. virtual
  911. #endif
  912. SqlDouble GetSqlDouble (int i)
  913. {
  914. object value = GetSqlValue (i);
  915. if (!(value is SqlDouble))
  916. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  917. return (SqlDouble) value;
  918. }
  919. public
  920. #if NET_2_0
  921. virtual
  922. #endif
  923. SqlGuid GetSqlGuid (int i)
  924. {
  925. object value = GetSqlValue (i);
  926. if (!(value is SqlGuid))
  927. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  928. return (SqlGuid) value;
  929. }
  930. public
  931. #if NET_2_0
  932. virtual
  933. #endif
  934. SqlInt16 GetSqlInt16 (int i)
  935. {
  936. object value = GetSqlValue (i);
  937. if (!(value is SqlInt16))
  938. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  939. return (SqlInt16) value;
  940. }
  941. public
  942. #if NET_2_0
  943. virtual
  944. #endif
  945. SqlInt32 GetSqlInt32 (int i)
  946. {
  947. object value = GetSqlValue (i);
  948. if (!(value is SqlInt32))
  949. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  950. return (SqlInt32) value;
  951. }
  952. public
  953. #if NET_2_0
  954. virtual
  955. #endif
  956. SqlInt64 GetSqlInt64 (int i)
  957. {
  958. object value = GetSqlValue (i);
  959. // TDS 7.0 returns bigint as decimal(19,0)
  960. if (value is SqlDecimal) {
  961. TdsDataColumn schema = command.Tds.Columns[i];
  962. byte precision, scale;
  963. #if NET_2_0
  964. precision = (byte)schema.NumericPrecision;
  965. scale = (byte)schema.NumericScale;
  966. #else
  967. precision = (byte)schema["NumericPrecision"];
  968. scale = (byte)schema["NumericScale"];
  969. #endif
  970. if (precision == 19 && scale == 0)
  971. value = (SqlInt64) (SqlDecimal) value;
  972. }
  973. if (!(value is SqlInt64))
  974. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  975. return (SqlInt64) value;
  976. }
  977. public
  978. #if NET_2_0
  979. virtual
  980. #endif
  981. SqlMoney GetSqlMoney (int i)
  982. {
  983. object value = GetSqlValue (i);
  984. if (!(value is SqlMoney))
  985. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  986. return (SqlMoney) value;
  987. }
  988. public
  989. #if NET_2_0
  990. virtual
  991. #endif
  992. SqlSingle GetSqlSingle (int i)
  993. {
  994. object value = GetSqlValue (i);
  995. if (!(value is SqlSingle))
  996. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  997. return (SqlSingle) value;
  998. }
  999. public
  1000. #if NET_2_0
  1001. virtual
  1002. #endif
  1003. SqlString GetSqlString (int i)
  1004. {
  1005. object value = GetSqlValue (i);
  1006. if (!(value is SqlString))
  1007. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  1008. return (SqlString) value;
  1009. }
  1010. #if NET_2_0
  1011. public virtual SqlXml GetSqlXml (int i)
  1012. {
  1013. object value = GetSqlValue (i);
  1014. if (!(value is SqlXml)) {
  1015. if (value is DBNull) {
  1016. throw new SqlNullValueException ();
  1017. } else if (command.Tds.TdsVersion == TdsVersion.tds70 && value is SqlString) {
  1018. // Workaround for TDS 7 clients
  1019. // Xml column types are supported only from Sql Server 2005 / TDS 8, however
  1020. // when a TDS 7 client requests for Xml column data, Sql Server 2005 returns
  1021. // it as NTEXT
  1022. MemoryStream stream = null;
  1023. if (!((SqlString) value).IsNull)
  1024. stream = new MemoryStream (Encoding.Unicode.GetBytes (value.ToString()));
  1025. value = new SqlXml (stream);
  1026. } else {
  1027. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  1028. }
  1029. }
  1030. return (SqlXml) value;
  1031. }
  1032. #endif // NET_2_0
  1033. public
  1034. #if NET_2_0
  1035. virtual
  1036. #endif
  1037. object GetSqlValue (int i)
  1038. {
  1039. int dbType, csize;
  1040. TdsColumnType ctype;
  1041. if (i < 0 || i >= command.Tds.Columns.Count)
  1042. throw new IndexOutOfRangeException ();
  1043. #if NET_2_0
  1044. ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
  1045. csize = (int) command.Tds.Columns[i].ColumnSize;
  1046. #else
  1047. ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
  1048. csize = (int) command.Tds.Columns[i]["ColumnSize"];
  1049. #endif
  1050. GetSchemaRowDbType (ctype, csize, out dbType);
  1051. SqlDbType type = (SqlDbType) dbType;
  1052. object value = GetValue (i);
  1053. switch (type) {
  1054. case SqlDbType.BigInt:
  1055. if (value == DBNull.Value)
  1056. return SqlInt64.Null;
  1057. return (SqlInt64) ((long) value);
  1058. case SqlDbType.Binary:
  1059. case SqlDbType.Image:
  1060. case SqlDbType.VarBinary:
  1061. case SqlDbType.Timestamp:
  1062. if (value == DBNull.Value)
  1063. return SqlBinary.Null;
  1064. return (SqlBinary) ((byte[]) value);
  1065. case SqlDbType.Bit:
  1066. if (value == DBNull.Value)
  1067. return SqlBoolean.Null;
  1068. return (SqlBoolean) ((bool) value);
  1069. case SqlDbType.Char:
  1070. case SqlDbType.NChar:
  1071. case SqlDbType.NText:
  1072. case SqlDbType.NVarChar:
  1073. case SqlDbType.Text:
  1074. case SqlDbType.VarChar:
  1075. if (value == DBNull.Value)
  1076. return SqlString.Null;
  1077. return (SqlString) ((string) value);
  1078. case SqlDbType.DateTime:
  1079. case SqlDbType.SmallDateTime:
  1080. if (value == DBNull.Value)
  1081. return SqlDateTime.Null;
  1082. return (SqlDateTime) ((DateTime) value);
  1083. case SqlDbType.Decimal:
  1084. if (value == DBNull.Value)
  1085. return SqlDecimal.Null;
  1086. if (value is TdsBigDecimal)
  1087. return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
  1088. return (SqlDecimal) ((decimal) value);
  1089. case SqlDbType.Float:
  1090. if (value == DBNull.Value)
  1091. return SqlDouble.Null;
  1092. return (SqlDouble) ((double) value);
  1093. case SqlDbType.Int:
  1094. if (value == DBNull.Value)
  1095. return SqlInt32.Null;
  1096. return (SqlInt32) ((int) value);
  1097. case SqlDbType.Money:
  1098. case SqlDbType.SmallMoney:
  1099. if (value == DBNull.Value)
  1100. return SqlMoney.Null;
  1101. return (SqlMoney) ((decimal) value);
  1102. case SqlDbType.Real:
  1103. if (value == DBNull.Value)
  1104. return SqlSingle.Null;
  1105. return (SqlSingle) ((float) value);
  1106. case SqlDbType.UniqueIdentifier:
  1107. if (value == DBNull.Value)
  1108. return SqlGuid.Null;
  1109. return (SqlGuid) ((Guid) value);
  1110. case SqlDbType.SmallInt:
  1111. if (value == DBNull.Value)
  1112. return SqlInt16.Null;
  1113. return (SqlInt16) ((short) value);
  1114. case SqlDbType.TinyInt:
  1115. if (value == DBNull.Value)
  1116. return SqlByte.Null;
  1117. return (SqlByte) ((byte) value);
  1118. #if NET_2_0
  1119. case SqlDbType.Xml:
  1120. if (value == DBNull.Value)
  1121. return SqlByte.Null;
  1122. return (SqlXml) value;
  1123. #endif
  1124. }
  1125. throw new InvalidOperationException ("The type of this column is unknown.");
  1126. }
  1127. public
  1128. #if NET_2_0
  1129. virtual
  1130. #endif
  1131. int GetSqlValues (object[] values)
  1132. {
  1133. int count = 0;
  1134. int columnCount = command.Tds.Columns.Count;
  1135. int arrayCount = values.Length;
  1136. if (arrayCount > columnCount)
  1137. count = columnCount;
  1138. else
  1139. count = arrayCount;
  1140. for (int i = 0; i < count; i += 1)
  1141. values [i] = GetSqlValue (i);
  1142. return count;
  1143. }
  1144. public
  1145. #if NET_2_0
  1146. override
  1147. #endif // NET_2_0
  1148. string GetString (int i)
  1149. {
  1150. object value = GetValue (i);
  1151. if (!(value is string)) {
  1152. if (value is DBNull) throw new SqlNullValueException ();
  1153. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  1154. }
  1155. return (string) value;
  1156. }
  1157. public
  1158. #if NET_2_0
  1159. override
  1160. #endif // NET_2_0
  1161. object GetValue (int i)
  1162. {
  1163. if (i < 0 || i >= command.Tds.Columns.Count)
  1164. throw new IndexOutOfRangeException ();
  1165. try {
  1166. if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
  1167. return ((Tds)command.Tds).GetSequentialColumnValue (i);
  1168. }
  1169. } catch (TdsInternalException ex) {
  1170. command.Connection.Close ();
  1171. throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
  1172. }
  1173. return command.Tds.ColumnValues [i];
  1174. }
  1175. public
  1176. #if NET_2_0
  1177. override
  1178. #endif // NET_2_0
  1179. int GetValues (object[] values)
  1180. {
  1181. int len = values.Length;
  1182. int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
  1183. // If a four-byte decimal is stored, then we can't convert to
  1184. // a native type. Throw an OverflowException.
  1185. if (bigDecimalIndex >= 0 && bigDecimalIndex < len)
  1186. throw new OverflowException ();
  1187. try {
  1188. command.Tds.ColumnValues.CopyTo (0, values, 0,
  1189. len > command.Tds.ColumnValues.Count ? command.Tds.ColumnValues.Count : len);
  1190. } catch (TdsInternalException ex) {
  1191. command.Connection.Close ();
  1192. throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
  1193. }
  1194. return (len < FieldCount ? len : FieldCount);
  1195. }
  1196. #if !NET_2_0
  1197. void IDisposable.Dispose ()
  1198. {
  1199. Dispose (true);
  1200. GC.SuppressFinalize (this);
  1201. }
  1202. #endif
  1203. #if NET_2_0
  1204. public override IEnumerator GetEnumerator ()
  1205. #else
  1206. IEnumerator IEnumerable.GetEnumerator ()
  1207. #endif
  1208. {
  1209. return new DbEnumerator (this);
  1210. }
  1211. public
  1212. #if NET_2_0
  1213. override
  1214. #endif // NET_2_0
  1215. bool IsDBNull (int i)
  1216. {
  1217. return GetValue (i) == DBNull.Value;
  1218. }
  1219. public
  1220. #if NET_2_0
  1221. override
  1222. #endif // NET_2_0
  1223. bool NextResult ()
  1224. {
  1225. ValidateState ();
  1226. if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
  1227. return false;
  1228. try {
  1229. moreResults = command.Tds.NextResult ();
  1230. } catch (TdsInternalException ex) {
  1231. command.Connection.Close ();
  1232. throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
  1233. }
  1234. if (!moreResults)
  1235. command.GetOutputParameters ();
  1236. else {
  1237. // new schema - don't do anything except reset schemaTable as command.Tds.Columns is already updated
  1238. schemaTable = null;
  1239. dataTypeNames = null;
  1240. }
  1241. rowsRead = 0;
  1242. resultsRead += 1;
  1243. return moreResults;
  1244. }
  1245. public
  1246. #if NET_2_0
  1247. override
  1248. #endif // NET_2_0
  1249. bool Read ()
  1250. {
  1251. ValidateState ();
  1252. if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
  1253. return false;
  1254. if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
  1255. return false;
  1256. if (!moreResults)
  1257. return false;
  1258. if ((haveRead) && (!readResultUsed))
  1259. {
  1260. readResultUsed = true;
  1261. return true;
  1262. }
  1263. return (ReadRecord ());
  1264. }
  1265. internal bool ReadRecord ()
  1266. {
  1267. try {
  1268. bool result = command.Tds.NextRow ();
  1269. rowsRead += 1;
  1270. return result;
  1271. } catch (TdsInternalException ex) {
  1272. command.Connection.Close ();
  1273. throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
  1274. }
  1275. }
  1276. void ValidateState ()
  1277. {
  1278. if (IsClosed)
  1279. throw new InvalidOperationException ("Invalid attempt to read data when reader is closed");
  1280. }
  1281. #if NET_2_0
  1282. public override Type GetProviderSpecificFieldType (int i)
  1283. {
  1284. return (GetSqlValue (i).GetType());
  1285. }
  1286. public override object GetProviderSpecificValue (int i)
  1287. {
  1288. return (GetSqlValue (i));
  1289. }
  1290. public override int GetProviderSpecificValues (object [] values)
  1291. {
  1292. return (GetSqlValues (values));
  1293. }
  1294. public virtual SqlBytes GetSqlBytes (int i)
  1295. {
  1296. //object value = GetSqlValue (i);
  1297. //if (!(value is SqlBinary))
  1298. // throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  1299. Byte[] val = (byte[])GetValue(i);
  1300. SqlBytes sb = new SqlBytes (val);
  1301. return (sb);
  1302. }
  1303. #endif // NET_2_0
  1304. #endregion // Methods
  1305. }
  1306. }