SqlDataReader.cs 37 KB

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