DataTableReader.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. //------------------------------------------------------------------------------
  2. // <copyright file="DataTableReader.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. // <owner current="false" primary="false">[....]</owner>
  8. //------------------------------------------------------------------------------
  9. namespace System.Data {
  10. using System;
  11. using System.Data.Common;
  12. using System.Data.SqlTypes;
  13. using System.Collections;
  14. using System.ComponentModel;
  15. public sealed class DataTableReader : DbDataReader {
  16. private readonly DataTable[] tables = null;
  17. private bool isOpen = true;
  18. private DataTable schemaTable = null;
  19. private int tableCounter = -1;
  20. private int rowCounter = -1;
  21. private DataTable currentDataTable = null;
  22. private DataRow currentDataRow = null;
  23. private bool hasRows= true;
  24. private bool reachEORows = false;
  25. private bool currentRowRemoved = false;
  26. private bool schemaIsChanged = false;
  27. private bool started = false;
  28. private bool readerIsInvalid = false;
  29. private DataTableReaderListener listener = null;
  30. private bool tableCleared = false;
  31. public DataTableReader(DataTable dataTable) {
  32. if (dataTable == null)
  33. throw ExceptionBuilder.ArgumentNull("DataTable");
  34. tables = new DataTable[1] {dataTable};
  35. init();
  36. // schemaTable = GetSchemaTableFromDataTable(currentDataTable);
  37. }
  38. public DataTableReader(DataTable [] dataTables) {
  39. if (dataTables == null)
  40. throw ExceptionBuilder.ArgumentNull("DataTable");
  41. if (dataTables.Length == 0)
  42. throw ExceptionBuilder.DataTableReaderArgumentIsEmpty();
  43. tables = new DataTable[dataTables.Length];
  44. for (int i = 0; i < dataTables.Length ; i++) {
  45. if (dataTables[i] == null)
  46. throw ExceptionBuilder.ArgumentNull("DataTable");
  47. tables[i] = dataTables[i];
  48. }
  49. init();
  50. // schemaTable = GetSchemaTableFromDataTable(currentDataTable);
  51. }
  52. private bool ReaderIsInvalid {
  53. get {
  54. return readerIsInvalid;
  55. }
  56. set {
  57. if (readerIsInvalid == value)
  58. return;
  59. readerIsInvalid = value;
  60. if (readerIsInvalid && listener != null) {
  61. listener.CleanUp();
  62. }
  63. }
  64. }
  65. private bool IsSchemaChanged {
  66. get {
  67. return schemaIsChanged;
  68. }
  69. set {
  70. if (!value || schemaIsChanged == value) //once it is set to false; should not change unless in init() or NextResult()
  71. return;
  72. schemaIsChanged = value;
  73. if (listener != null) {
  74. listener.CleanUp();
  75. }
  76. }
  77. }
  78. internal DataTable CurrentDataTable {
  79. get {
  80. return currentDataTable;
  81. }
  82. }
  83. private void init() {
  84. tableCounter = 0;
  85. reachEORows = false;
  86. schemaIsChanged = false;
  87. currentDataTable = tables[tableCounter];
  88. hasRows = (currentDataTable.Rows.Count > 0);
  89. ReaderIsInvalid = false;
  90. // we need to listen to current tables event so create a listener, it will listen to events and call us back.
  91. listener = new DataTableReaderListener(this);
  92. }
  93. override public void Close() {
  94. if (!isOpen)
  95. return;
  96. // no need to listen to events after close
  97. if (listener != null)
  98. listener.CleanUp();
  99. listener = null;
  100. schemaTable = null;
  101. isOpen = false;
  102. }
  103. override public DataTable GetSchemaTable(){
  104. ValidateOpen("GetSchemaTable");
  105. ValidateReader();
  106. // each time, we just get schema table of current table for once, no need to recreate each time, if schema is changed, reader is already
  107. // is invalid
  108. if (schemaTable == null)
  109. schemaTable = GetSchemaTableFromDataTable(currentDataTable);
  110. return schemaTable;
  111. }
  112. override public bool NextResult() {
  113. // next result set; reset everything
  114. ValidateOpen("NextResult");
  115. if ((tableCounter == tables.Length -1))
  116. return false;
  117. currentDataTable = tables[++tableCounter];
  118. if (listener != null)
  119. listener.UpdataTable(currentDataTable); // it will unsubscribe from preveous tables events and subscribe to new table's events
  120. schemaTable = null;
  121. rowCounter = -1;
  122. currentRowRemoved = false;
  123. reachEORows = false;
  124. schemaIsChanged = false;
  125. started = false;
  126. ReaderIsInvalid = false;
  127. tableCleared = false;
  128. hasRows = (currentDataTable.Rows.Count > 0);
  129. return true;
  130. }
  131. override public bool Read() {
  132. /* else if (tableCleared) {
  133. return false;
  134. throw ExceptionBuilder.EmptyDataTableReader(currentDataTable.TableName);
  135. }
  136. */
  137. if (!started) {
  138. started = true;
  139. }
  140. /*else {
  141. ValidateRow(rowCounter);
  142. }*/
  143. ValidateOpen("Read");
  144. ValidateReader();
  145. if(reachEORows) {
  146. return false;
  147. }
  148. if (rowCounter >= currentDataTable.Rows.Count -1 ) {
  149. reachEORows = true;
  150. if (listener != null)
  151. listener.CleanUp();
  152. return false;
  153. }
  154. rowCounter ++;
  155. ValidateRow(rowCounter);
  156. currentDataRow = currentDataTable.Rows[rowCounter];
  157. while (currentDataRow.RowState == DataRowState.Deleted) {
  158. rowCounter++;
  159. if (rowCounter == currentDataTable.Rows.Count) {
  160. reachEORows = true;
  161. if (listener != null)
  162. listener.CleanUp();
  163. return false;
  164. }
  165. ValidateRow(rowCounter);
  166. currentDataRow = currentDataTable.Rows[rowCounter];
  167. }
  168. if (currentRowRemoved)
  169. currentRowRemoved = false;
  170. return true;
  171. }
  172. override public int Depth {
  173. get {
  174. ValidateOpen("Depth");
  175. ValidateReader();
  176. return 0;
  177. }
  178. }
  179. override public bool IsClosed {
  180. get {
  181. return (!isOpen);
  182. }
  183. }
  184. override public int RecordsAffected {
  185. get {
  186. ValidateReader();
  187. return 0;
  188. }
  189. }
  190. override public bool HasRows {
  191. get {
  192. ValidateOpen("HasRows");
  193. ValidateReader();
  194. return hasRows;
  195. }
  196. }
  197. override public object this[int ordinal] {
  198. get {
  199. ValidateOpen("Item");
  200. ValidateReader();
  201. if ((currentDataRow == null) || (currentDataRow.RowState == DataRowState.Deleted)) {
  202. ReaderIsInvalid = true;
  203. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  204. }
  205. try {
  206. return currentDataRow[ordinal];
  207. }
  208. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  209. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  210. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  211. }
  212. }
  213. }
  214. override public object this[string name] {
  215. get {
  216. ValidateOpen("Item");
  217. ValidateReader();
  218. if ((currentDataRow == null) || (currentDataRow.RowState == DataRowState.Deleted)) {
  219. ReaderIsInvalid = true;
  220. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  221. }
  222. return currentDataRow[name];
  223. }
  224. }
  225. override public Int32 FieldCount {
  226. get {
  227. ValidateOpen("FieldCount");
  228. ValidateReader();
  229. return currentDataTable.Columns.Count;
  230. }
  231. }
  232. override public Type GetProviderSpecificFieldType(int ordinal) {
  233. ValidateOpen("GetProviderSpecificFieldType");
  234. ValidateReader();
  235. return GetFieldType(ordinal);
  236. }
  237. override public Object GetProviderSpecificValue(int ordinal) {
  238. ValidateOpen("GetProviderSpecificValue");
  239. ValidateReader();
  240. return GetValue(ordinal);
  241. }
  242. override public int GetProviderSpecificValues(object[] values) {
  243. ValidateOpen("GetProviderSpecificValues");
  244. ValidateReader();
  245. return GetValues(values);
  246. }
  247. override public bool GetBoolean (int ordinal) {
  248. ValidateState("GetBoolean");
  249. ValidateReader();
  250. try {
  251. return (bool) currentDataRow[ordinal];
  252. }
  253. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  254. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  255. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  256. }
  257. }
  258. override public byte GetByte (int ordinal) {
  259. ValidateState("GetByte");
  260. ValidateReader();
  261. try {
  262. return (byte) currentDataRow[ordinal];
  263. }
  264. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  265. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  266. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  267. }
  268. }
  269. override public long GetBytes(int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length) {
  270. ValidateState("GetBytes");
  271. ValidateReader();
  272. byte[] tempBuffer;
  273. try {
  274. tempBuffer = (byte[]) currentDataRow[ordinal];
  275. }
  276. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  277. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  278. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  279. }
  280. if (buffer == null) {
  281. return tempBuffer.Length;
  282. }
  283. int srcIndex = (int) dataIndex;
  284. int byteCount = Math.Min(tempBuffer.Length - srcIndex, length);
  285. if (srcIndex < 0) {
  286. throw ADP.InvalidSourceBufferIndex(tempBuffer.Length, srcIndex, "dataIndex");
  287. }
  288. else if ((bufferIndex < 0) || (bufferIndex > 0 && bufferIndex >= buffer.Length)) {
  289. throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, "bufferIndex");
  290. }
  291. if (0 < byteCount) {
  292. Array.Copy(tempBuffer, dataIndex, buffer, bufferIndex, byteCount);
  293. }
  294. else if (length < 0) {
  295. throw ADP.InvalidDataLength(length);
  296. }
  297. else {
  298. byteCount = 0;
  299. }
  300. return byteCount;
  301. }
  302. override public char GetChar (int ordinal) {
  303. ValidateState("GetChar");
  304. ValidateReader();
  305. try {
  306. return (char) currentDataRow[ordinal];
  307. }
  308. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  309. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  310. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  311. }
  312. }
  313. override public long GetChars(int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length) {
  314. ValidateState("GetChars");
  315. ValidateReader();
  316. char[] tempBuffer;
  317. try {
  318. tempBuffer = (char[]) currentDataRow[ordinal];
  319. }
  320. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  321. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  322. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  323. }
  324. if (buffer == null) {
  325. return tempBuffer.Length;
  326. }
  327. int srcIndex = (int) dataIndex;
  328. int charCount = Math.Min(tempBuffer.Length - srcIndex, length);
  329. if (srcIndex < 0) {
  330. throw ADP.InvalidSourceBufferIndex(tempBuffer.Length, srcIndex, "dataIndex");
  331. }
  332. else if ((bufferIndex < 0) || (bufferIndex > 0 && bufferIndex >= buffer.Length)) {
  333. throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, "bufferIndex");
  334. }
  335. if (0 < charCount) {
  336. Array.Copy(tempBuffer, dataIndex, buffer, bufferIndex, charCount);
  337. }
  338. else if (length < 0) {
  339. throw ADP.InvalidDataLength(length);
  340. }
  341. else {
  342. charCount = 0;
  343. }
  344. return charCount;
  345. }
  346. override public String GetDataTypeName (int ordinal) {
  347. ValidateOpen("GetDataTypeName");
  348. ValidateReader();
  349. return ((Type)GetFieldType(ordinal)).Name;
  350. }
  351. override public DateTime GetDateTime (int ordinal) {
  352. ValidateState("GetDateTime");
  353. ValidateReader();
  354. try {
  355. return (DateTime) currentDataRow[ordinal];
  356. }
  357. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  358. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  359. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  360. }
  361. }
  362. override public Decimal GetDecimal (int ordinal) {
  363. ValidateState("GetDecimal");
  364. ValidateReader();
  365. try {
  366. return (Decimal) currentDataRow[ordinal];
  367. }
  368. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  369. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  370. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  371. }
  372. }
  373. override public Double GetDouble (int ordinal) {
  374. ValidateState("GetDouble");
  375. ValidateReader();
  376. try {
  377. return (double) currentDataRow[ordinal];
  378. }
  379. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  380. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  381. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  382. }
  383. }
  384. override public Type GetFieldType (int ordinal) {
  385. ValidateOpen("GetFieldType");
  386. ValidateReader();
  387. try {
  388. return (currentDataTable.Columns[ordinal].DataType);
  389. }
  390. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  391. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  392. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  393. }
  394. }
  395. override public Single GetFloat (int ordinal) {
  396. ValidateState("GetFloat");
  397. ValidateReader();
  398. try {
  399. return (Single) currentDataRow[ordinal];
  400. }
  401. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  402. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  403. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  404. }
  405. }
  406. override public Guid GetGuid (int ordinal) {
  407. ValidateState("GetGuid");
  408. ValidateReader();
  409. try {
  410. return (Guid) currentDataRow[ordinal];
  411. }
  412. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  413. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  414. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  415. }
  416. }
  417. override public Int16 GetInt16 (int ordinal) {
  418. ValidateState("GetInt16");
  419. ValidateReader();
  420. try {
  421. return (Int16) currentDataRow[ordinal];
  422. }
  423. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  424. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  425. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  426. }
  427. }
  428. override public Int32 GetInt32 (int ordinal) {
  429. ValidateState("GetInt32");
  430. ValidateReader();
  431. try {
  432. return (Int32) currentDataRow[ordinal];
  433. }
  434. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  435. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  436. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  437. }
  438. }
  439. override public Int64 GetInt64 (int ordinal) {
  440. ValidateState("GetInt64");
  441. ValidateReader();
  442. try {
  443. return (Int64) currentDataRow[ordinal];
  444. }
  445. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  446. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  447. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  448. }
  449. }
  450. override public String GetName (int ordinal) {
  451. ValidateOpen("GetName");
  452. ValidateReader();
  453. try {
  454. return (currentDataTable.Columns[ordinal].ColumnName);
  455. }
  456. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  457. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  458. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  459. }
  460. }
  461. override public Int32 GetOrdinal (string name) {
  462. ValidateOpen("GetOrdinal");
  463. ValidateReader();
  464. DataColumn dc = currentDataTable.Columns[name];
  465. if (dc != null) {
  466. return dc.Ordinal;// WebData 113248
  467. }
  468. else{
  469. throw ExceptionBuilder.ColumnNotInTheTable(name, currentDataTable.TableName);
  470. }
  471. }
  472. override public string GetString (int ordinal) {
  473. ValidateState("GetString");
  474. ValidateReader();
  475. try {
  476. return (string) currentDataRow[ordinal];
  477. }
  478. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  479. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  480. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  481. }
  482. }
  483. override public object GetValue (int ordinal) {
  484. ValidateState("GetValue");
  485. ValidateReader();
  486. try {
  487. return currentDataRow[ordinal];
  488. }
  489. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  490. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  491. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  492. }
  493. }
  494. override public Int32 GetValues (object[] values) {
  495. ValidateState("GetValues");
  496. ValidateReader();
  497. if (values ==null)
  498. throw ExceptionBuilder.ArgumentNull("values");
  499. Array.Copy(currentDataRow.ItemArray, values, currentDataRow.ItemArray.Length > values.Length ? values.Length : currentDataRow.ItemArray.Length);
  500. return (currentDataRow.ItemArray.Length > values.Length ? values.Length : currentDataRow.ItemArray.Length);
  501. }
  502. override public bool IsDBNull (int ordinal) {
  503. ValidateState("IsDBNull");
  504. ValidateReader();
  505. try {
  506. return (currentDataRow.IsNull(ordinal));
  507. }
  508. catch(IndexOutOfRangeException e) { // thrown by DataColumnCollection
  509. ExceptionBuilder.TraceExceptionWithoutRethrow(e);
  510. throw ExceptionBuilder.ArgumentOutOfRange("ordinal");
  511. }
  512. }
  513. // IEnumerable
  514. override public IEnumerator GetEnumerator() {
  515. ValidateOpen("GetEnumerator");
  516. return new DbEnumerator((IDataReader)this);
  517. }
  518. static internal DataTable GetSchemaTableFromDataTable(DataTable table) {
  519. if (table == null) {
  520. throw ExceptionBuilder.ArgumentNull("DataTable");
  521. }
  522. DataTable tempSchemaTable = new DataTable("SchemaTable");
  523. tempSchemaTable.Locale = System.Globalization.CultureInfo.InvariantCulture;
  524. DataColumn ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(System.String));
  525. DataColumn ColumnOrdinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(System.Int32));
  526. DataColumn ColumnSize = new DataColumn(SchemaTableColumn.ColumnSize, typeof(System.Int32));
  527. DataColumn NumericPrecision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(System.Int16));
  528. DataColumn NumericScale = new DataColumn(SchemaTableColumn.NumericScale, typeof(System.Int16));
  529. DataColumn DataType = new DataColumn(SchemaTableColumn.DataType, typeof(System.Type));
  530. DataColumn ProviderType = new DataColumn(SchemaTableColumn.ProviderType, typeof(System.Int32));
  531. DataColumn IsLong = new DataColumn(SchemaTableColumn.IsLong, typeof(System.Boolean));
  532. DataColumn AllowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(System.Boolean));
  533. DataColumn IsReadOnly = new DataColumn(SchemaTableOptionalColumn.IsReadOnly, typeof(System.Boolean));
  534. DataColumn IsRowVersion = new DataColumn(SchemaTableOptionalColumn.IsRowVersion, typeof(System.Boolean));
  535. DataColumn IsUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(System.Boolean));
  536. DataColumn IsKeyColumn = new DataColumn(SchemaTableColumn.IsKey, typeof(System.Boolean));
  537. DataColumn IsAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(System.Boolean));
  538. DataColumn BaseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(System.String));
  539. DataColumn BaseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(System.String));
  540. DataColumn BaseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(System.String));
  541. DataColumn BaseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(System.String));
  542. DataColumn AutoIncrementSeed = new DataColumn(SchemaTableOptionalColumn.AutoIncrementSeed, typeof(System.Int64));
  543. DataColumn AutoIncrementStep = new DataColumn(SchemaTableOptionalColumn.AutoIncrementStep, typeof(System.Int64));
  544. DataColumn DefaultValue = new DataColumn(SchemaTableOptionalColumn.DefaultValue, typeof(System.Object));
  545. DataColumn Expression = new DataColumn(SchemaTableOptionalColumn.Expression, typeof(System.String));
  546. DataColumn ColumnMapping = new DataColumn(SchemaTableOptionalColumn.ColumnMapping, typeof(System.Data.MappingType));
  547. DataColumn BaseTableNamespace = new DataColumn(SchemaTableOptionalColumn.BaseTableNamespace, typeof(System.String));
  548. DataColumn BaseColumnNamespace = new DataColumn(SchemaTableOptionalColumn.BaseColumnNamespace, typeof(System.String));
  549. ColumnSize.DefaultValue = -1;
  550. if (table.DataSet != null)
  551. BaseCatalogName.DefaultValue = table.DataSet.DataSetName;
  552. BaseTableName.DefaultValue = table.TableName;
  553. BaseTableNamespace.DefaultValue = table.Namespace;
  554. IsRowVersion.DefaultValue = false;
  555. IsLong.DefaultValue = false;
  556. IsReadOnly.DefaultValue = false;
  557. IsKeyColumn.DefaultValue = false;
  558. IsAutoIncrement.DefaultValue = false;
  559. AutoIncrementSeed.DefaultValue = 0;
  560. AutoIncrementStep.DefaultValue = 1;
  561. tempSchemaTable.Columns.Add(ColumnName);
  562. tempSchemaTable.Columns.Add(ColumnOrdinal);
  563. tempSchemaTable.Columns.Add(ColumnSize);
  564. tempSchemaTable.Columns.Add(NumericPrecision);
  565. tempSchemaTable.Columns.Add(NumericScale);
  566. tempSchemaTable.Columns.Add(DataType);
  567. tempSchemaTable.Columns.Add(ProviderType);
  568. tempSchemaTable.Columns.Add(IsLong);
  569. tempSchemaTable.Columns.Add(AllowDBNull);
  570. tempSchemaTable.Columns.Add(IsReadOnly);
  571. tempSchemaTable.Columns.Add(IsRowVersion);
  572. tempSchemaTable.Columns.Add(IsUnique);
  573. tempSchemaTable.Columns.Add(IsKeyColumn);
  574. tempSchemaTable.Columns.Add(IsAutoIncrement);
  575. tempSchemaTable.Columns.Add(BaseCatalogName);
  576. tempSchemaTable.Columns.Add(BaseSchemaName);
  577. // specific to datatablereader
  578. tempSchemaTable.Columns.Add(BaseTableName);
  579. tempSchemaTable.Columns.Add(BaseColumnName);
  580. tempSchemaTable.Columns.Add(AutoIncrementSeed);
  581. tempSchemaTable.Columns.Add(AutoIncrementStep);
  582. tempSchemaTable.Columns.Add(DefaultValue);
  583. tempSchemaTable.Columns.Add(Expression);
  584. tempSchemaTable.Columns.Add(ColumnMapping);
  585. tempSchemaTable.Columns.Add(BaseTableNamespace);
  586. tempSchemaTable.Columns.Add(BaseColumnNamespace);
  587. foreach (DataColumn dc in table.Columns) {
  588. DataRow dr = tempSchemaTable.NewRow();
  589. dr[ColumnName] = dc.ColumnName;
  590. dr[ColumnOrdinal] = dc.Ordinal;
  591. dr[DataType] = dc.DataType;
  592. if (dc.DataType == typeof(string)) {
  593. dr[ColumnSize] = dc.MaxLength;
  594. }
  595. dr[AllowDBNull] = dc.AllowDBNull;
  596. dr[IsReadOnly] = dc.ReadOnly;
  597. dr[IsUnique] = dc.Unique;
  598. if (dc.AutoIncrement) {
  599. dr[IsAutoIncrement] = true;
  600. dr[AutoIncrementSeed] = dc.AutoIncrementSeed;
  601. dr[AutoIncrementStep] = dc.AutoIncrementStep;
  602. }
  603. if (dc.DefaultValue != DBNull.Value)
  604. dr[DefaultValue] = dc.DefaultValue;
  605. if (dc.Expression.Length != 0) {
  606. bool hasExternalDependency = false;
  607. DataColumn[] dependency = dc.DataExpression.GetDependency();
  608. for (int j = 0; j < dependency.Length; j++) {
  609. if (dependency[j].Table != table) {
  610. hasExternalDependency = true;
  611. break;
  612. }
  613. }
  614. if (!hasExternalDependency)
  615. dr[Expression] = dc.Expression;
  616. }
  617. dr[ColumnMapping] = dc.ColumnMapping;
  618. dr[BaseColumnName] = dc.ColumnName;
  619. dr[BaseColumnNamespace] = dc.Namespace;
  620. tempSchemaTable.Rows.Add(dr);
  621. }
  622. foreach(DataColumn key in table.PrimaryKey) {
  623. tempSchemaTable.Rows[key.Ordinal][IsKeyColumn] = true;
  624. }
  625. tempSchemaTable.AcceptChanges();
  626. return tempSchemaTable;
  627. }
  628. private void ValidateOpen(string caller) {
  629. if (!isOpen)
  630. throw ADP.DataReaderClosed(caller);
  631. }
  632. private void ValidateReader() {
  633. if (ReaderIsInvalid)
  634. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  635. if (IsSchemaChanged) {
  636. throw ExceptionBuilder.DataTableReaderSchemaIsInvalid(currentDataTable.TableName); // may be we can use better error message!
  637. }
  638. }
  639. private void ValidateState(string caller) {
  640. ValidateOpen(caller);
  641. if (tableCleared) {
  642. throw ExceptionBuilder.EmptyDataTableReader(currentDataTable.TableName);
  643. }
  644. // see if without any event raising, if our curent row has some changes!if so reader is invalid.
  645. if ((currentDataRow == null) || (currentDataTable == null) ) {//|| (currentDataRow != currentDataTable.Rows[rowCounter])) do we need thios check!
  646. ReaderIsInvalid = true;
  647. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  648. }
  649. //See if without any event raing, if our rows are deleted, or removed! Reader is not invalid, user should be able to read and reach goo row WebData98325
  650. if ((currentDataRow.RowState == DataRowState.Deleted) || (currentDataRow.RowState == DataRowState.Detached) ||currentRowRemoved)
  651. throw ExceptionBuilder.InvalidCurrentRowInDataTableReader();
  652. // user may have called clear (which removes the rows without raing event) or deleted part of rows without raising event!if so reader is invalid.
  653. if (0 > rowCounter ||currentDataTable.Rows.Count <= rowCounter) {
  654. ReaderIsInvalid = true;
  655. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  656. }
  657. else {
  658. }
  659. }
  660. private void ValidateRow(Int32 rowPosition) {
  661. if (ReaderIsInvalid)
  662. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  663. if (0 > rowPosition ||currentDataTable.Rows.Count <= rowPosition) {
  664. ReaderIsInvalid = true;
  665. throw ExceptionBuilder.InvalidDataTableReader(currentDataTable.TableName);
  666. }
  667. }
  668. // Event Call backs from DataTableReaderListener, will invoke these methods
  669. internal void SchemaChanged() {
  670. IsSchemaChanged = true;
  671. }
  672. internal void DataTableCleared() {
  673. if (!started)
  674. return;
  675. rowCounter = -1;
  676. if (!reachEORows)
  677. currentRowRemoved = true;
  678. }
  679. internal void DataChanged(DataRowChangeEventArgs args ) {
  680. if ((!started) ||(rowCounter == -1 && !tableCleared))
  681. return;
  682. /* if (rowCounter == -1 && tableCleared && args.Action == DataRowAction.Add) {
  683. tableCleared = false;
  684. return;
  685. }
  686. */
  687. switch (args.Action) {
  688. case DataRowAction.Add:
  689. ValidateRow(rowCounter + 1);
  690. /* if (tableCleared) {
  691. tableCleared = false;
  692. rowCounter++;
  693. currentDataRow = currentDataTable.Rows[rowCounter];
  694. currentRowRemoved = false;
  695. }
  696. else
  697. */
  698. if (currentDataRow == currentDataTable.Rows[rowCounter + 1]) { // check if we moved one position up
  699. rowCounter++; // if so, refresh the datarow and fix the counter
  700. }
  701. break;
  702. case DataRowAction.Delete: // delete
  703. case DataRowAction.Rollback:// rejectchanges
  704. case DataRowAction.Commit: // acceptchanges
  705. if ( args.Row.RowState == DataRowState.Detached ) {
  706. if (args.Row != currentDataRow) {
  707. if (rowCounter == 0) // if I am at first row and no previous row exist,NOOP
  708. break;
  709. ValidateRow(rowCounter -1);
  710. if (currentDataRow == currentDataTable.Rows[rowCounter - 1]) { // one of previous rows is detached, collection size is changed!
  711. rowCounter--;
  712. }
  713. }
  714. else { // we are proccessing current datarow
  715. currentRowRemoved = true;
  716. if (rowCounter > 0) { // go back one row, no matter what the state is
  717. rowCounter--;
  718. currentDataRow = currentDataTable.Rows[rowCounter];
  719. }
  720. else { // we are on 0th row, so reset data to initial state!
  721. rowCounter = -1;
  722. currentDataRow = null;
  723. }
  724. }
  725. }
  726. break;
  727. default:
  728. break;
  729. }
  730. }
  731. }
  732. }