Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Query / ResultAssembly / BridgeDataReader.cs
blob1fb083d0501b62ee6eaa74be4aebf706ddfe8cd8
1 //------------------------------------------------------------------------------
2 // <copyright file="BridgeDataReader.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // @owner Microsoft
6 // @backupOwner Microsoft
7 //---------------------------------------------------------------------
9 namespace System.Data.Query.ResultAssembly {
11 using System.Collections;
12 using System.Collections.Generic;
13 using System.ComponentModel;
14 using System.Data;
15 using System.Data.Common;
16 using System.Data.Common.Internal.Materialization;
17 using System.Data.Common.Utils;
18 using System.Data.Metadata.Edm;
19 using System.Data.Query.InternalTrees;
20 using System.Data.Query.PlanCompiler;
21 using System.Diagnostics;
23 /// <summary>
24 /// DbDataReader functionality for the bridge.
25 /// </summary>
26 internal sealed class BridgeDataReader : DbDataReader, IExtendedDataRecord {
28 #region private state
30 /// <summary>
31 /// Object that holds the state needed by the coordinator and the root enumerator
32 /// </summary>
33 private Shaper<RecordState> Shaper;
35 /// <summary>
36 /// Enumerator over shapers for NextResult() calls.
37 /// Null for nested data readers (depth > 0);
38 /// </summary>
39 private IEnumerator<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> NextResultShaperInfoEnumerator;
41 /// <summary>
42 /// The coordinator we're responsible for returning results for.
43 /// </summary>
44 private CoordinatorFactory<RecordState> CoordinatorFactory;
46 /// <summary>
47 /// The default record (pre-read/past-end) state
48 /// </summary>
49 private RecordState DefaultRecordState;
51 /// <summary>
52 /// We delegate to this on our getters, to avoid duplicate code.
53 /// </summary>
54 private BridgeDataRecord DataRecord;
56 /// <summary>
57 /// Do we have a row to read? Determined in the constructor and
58 /// should not be changed.
59 /// </summary>
60 private bool _hasRows;
62 /// <summary>
63 /// Set to true only when we've been closed through the Close() method
64 /// </summary>
65 private bool _isClosed;
67 #endregion
69 #region constructors
71 /// <summary>
72 /// Constructor used by the ResultColumn when doing GetValue, and by the Create factory
73 /// method.
74 /// </summary>
75 /// <param name="collection"></param>
76 /// <param name="isRoot"></param>
77 /// <param name="nextResultShaperInfos">enumrator of the shapers for NextResult() calls</param>
78 internal BridgeDataReader(Shaper<RecordState> shaper, CoordinatorFactory<RecordState> coordinatorFactory, int depth, IEnumerator<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> nextResultShaperInfos)
79 : base() {
80 Debug.Assert(null != shaper, "null shaper?");
81 Debug.Assert(null != coordinatorFactory, "null coordinatorFactory?");
82 Debug.Assert(depth == 0 || nextResultShaperInfos == null, "Nested data readers should not have multiple result sets.");
84 NextResultShaperInfoEnumerator = nextResultShaperInfos != null ? nextResultShaperInfos : null;
85 SetShaper(shaper, coordinatorFactory, depth);
88 private void SetShaper(Shaper<RecordState> shaper, CoordinatorFactory<RecordState> coordinatorFactory, int depth)
90 Shaper = shaper;
91 CoordinatorFactory = coordinatorFactory;
92 DataRecord = new BridgeDataRecord(shaper, depth);
94 // To determine whether there are any rows for this coordinator at this place in
95 // the root enumerator, we pretty much just look at it's current record (we'll read
96 // one if there isn't one waiting) and if it matches our coordinator, we've got rows.
97 _hasRows = false;
99 if (!Shaper.DataWaiting) {
100 Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
102 if (Shaper.DataWaiting) {
103 RecordState currentRecord = Shaper.RootEnumerator.Current;
105 if (null != currentRecord) {
106 _hasRows = (currentRecord.CoordinatorFactory == CoordinatorFactory);
110 // Once we've created the root enumerator, we can get the default record state
111 DefaultRecordState = coordinatorFactory.GetDefaultRecordState(Shaper);
112 Debug.Assert(null != DefaultRecordState, "no default?");
115 /// <summary>
116 /// The primary factory method to produce the BridgeDataReader; given a store data
117 /// reader and a column map, create the BridgeDataReader, hooking up the IteratorSources
118 /// and ResultColumn Hierarchy. All construction of top level data readers go through
119 /// this method.
120 /// </summary>
121 /// <param name="storeDataReader"></param>
122 /// <param name="columnMap">column map of the first result set</param>
123 /// <param name="nextResultColumnMaps">enumerable of the column maps for NextResult() calls.</param>
124 /// <returns></returns>
125 static internal DbDataReader Create(DbDataReader storeDataReader, ColumnMap columnMap, MetadataWorkspace workspace, IEnumerable<ColumnMap> nextResultColumnMaps) {
126 Debug.Assert(storeDataReader != null, "null storeDataReaders?");
127 Debug.Assert(columnMap != null, "null columnMap?");
128 Debug.Assert(workspace != null, "null workspace?");
130 var shaperInfo = CreateShaperInfo(storeDataReader, columnMap, workspace);
131 DbDataReader result = new BridgeDataReader(shaperInfo.Key, shaperInfo.Value, /*depth:*/ 0, GetNextResultShaperInfo(storeDataReader, workspace, nextResultColumnMaps).GetEnumerator());
132 return result;
135 private static KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>> CreateShaperInfo(DbDataReader storeDataReader, ColumnMap columnMap, MetadataWorkspace workspace)
137 Debug.Assert(storeDataReader != null, "null storeDataReaders?");
138 Debug.Assert(columnMap != null, "null columnMap?");
139 Debug.Assert(workspace != null, "null workspace?");
141 System.Data.Common.QueryCache.QueryCacheManager cacheManager = workspace.GetQueryCacheManager();
142 const System.Data.Objects.MergeOption NoTracking = System.Data.Objects.MergeOption.NoTracking;
144 ShaperFactory<RecordState> shaperFactory = Translator.TranslateColumnMap<RecordState>(cacheManager, columnMap, workspace, null, NoTracking, true);
145 Shaper<RecordState> recordShaper = shaperFactory.Create(storeDataReader, null, workspace, System.Data.Objects.MergeOption.NoTracking, true);
147 return new KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>(recordShaper, recordShaper.RootCoordinator.TypedCoordinatorFactory);
150 private static IEnumerable<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> GetNextResultShaperInfo(DbDataReader storeDataReader, MetadataWorkspace workspace, IEnumerable<ColumnMap> nextResultColumnMaps)
152 foreach (var nextResultColumnMap in nextResultColumnMaps)
154 yield return CreateShaperInfo(storeDataReader, nextResultColumnMap, workspace);
158 #endregion
160 #region helpers
162 /// <summary>
163 /// Implicitly close this (nested) data reader; will be called whenever
164 /// the user has done a GetValue() or a Read() on a parent reader/record
165 /// to ensure that we consume all our results. We do that because we
166 /// our design requires us to be positioned at the next nested reader's
167 /// first row.
168 /// </summary>
169 internal void CloseImplicitly() {
170 Consume();
171 DataRecord.CloseImplicitly();
174 /// <summary>
175 /// Reads to the end of the source enumerator provided
176 /// </summary>
177 private void Consume() {
178 while (ReadInternal()) ;
181 /// <summary>
182 /// Figure out the CLR type from the TypeMetadata object; For scalars,
183 /// we can get this from the metadata workspace, but for the rest, we
184 /// just guess at "Object". You need to use the DataRecordInfo property
185 /// to get better information for those.
186 /// </summary>
187 /// <param name="typeUsage"></param>
188 /// <returns></returns>
189 internal static Type GetClrTypeFromTypeMetadata(TypeUsage typeUsage) {
190 Type result;
192 PrimitiveType primitiveType;
193 if (TypeHelpers.TryGetEdmType<PrimitiveType>(typeUsage, out primitiveType)) {
194 result = primitiveType.ClrEquivalentType;
196 else {
197 if (TypeSemantics.IsReferenceType(typeUsage)) {
198 result = typeof(EntityKey);
200 else if (TypeUtils.IsStructuredType(typeUsage)) {
201 result = typeof(DbDataRecord);
203 else if (TypeUtils.IsCollectionType(typeUsage)) {
204 result = typeof(DbDataReader);
206 else if (TypeUtils.IsEnumerationType(typeUsage)) {
207 result = ((EnumType)typeUsage.EdmType).UnderlyingType.ClrEquivalentType;
209 else {
210 result = typeof(object);
213 return result;
216 #endregion
218 #region data reader specific properties and methods
220 /// <summary>
221 /// implementation for DbDataReader.Depth property
222 /// </summary>
223 override public int Depth {
224 get {
225 AssertReaderIsOpen("Depth");
226 return DataRecord.Depth;
230 /// <summary>
231 /// implementation for DbDataReader.HasRows property
232 /// </summary>
233 override public bool HasRows {
234 get {
235 AssertReaderIsOpen("HasRows");
236 return _hasRows;
240 /// <summary>
241 /// implementation for DbDataReader.IsClosed property
242 /// </summary>
243 override public bool IsClosed {
244 get {
245 // Rather that try and track this in two places; we just delegate
246 // to the data record that we constructed; it has more reasons to
247 // have to know this than we do in the data reader. (Of course,
248 // we look at our own closed state too...)
249 return ((_isClosed) || DataRecord.IsClosed);
253 /// <summary>
254 /// implementation for DbDataReader.RecordsAffected property
255 /// </summary>
256 override public int RecordsAffected {
257 get {
258 int result = -1; // For nested readers, return -1 which is the default for queries.
260 // We defer to the store reader for rows affected count. Note that for queries,
261 // the provider is generally expected to return -1.
263 if (DataRecord.Depth == 0) {
264 result = Shaper.Reader.RecordsAffected;
266 return result;
270 /// <summary>
271 /// Ensures that the reader is actually open, and throws an exception if not
272 /// </summary>
273 private void AssertReaderIsOpen(string methodName) {
274 if (IsClosed) {
275 if (DataRecord.IsImplicitlyClosed) {
276 throw EntityUtil.ImplicitlyClosedDataReaderError();
278 if (DataRecord.IsExplicitlyClosed) {
279 throw EntityUtil.DataReaderClosed(methodName);
284 /// <summary>
285 /// implementation for DbDataReader.Close() method
286 /// </summary>
287 override public void Close() {
288 // Make sure we explicitly closed the data record, since that's what
289 // where using to track closed state.
290 DataRecord.CloseExplicitly();
292 if (!_isClosed) {
293 _isClosed = true;
295 if (0 == DataRecord.Depth) {
296 // If we're the root collection, we want to ensure the remainder of
297 // the result column hierarchy is closed out, to avoid dangling
298 // references to it, should it be reused. We also want to physically
299 // close out the source reader as well.
300 Shaper.Reader.Close();
302 else {
303 // For non-root collections, we have to consume all the data, or we'll
304 // not be positioned propertly for what comes afterward.
305 Consume();
309 if (NextResultShaperInfoEnumerator != null)
311 NextResultShaperInfoEnumerator.Dispose();
312 NextResultShaperInfoEnumerator = null;
316 /// <summary>
317 /// implementation for DbDataReader.GetEnumerator() method
318 /// </summary>
319 [EditorBrowsableAttribute(EditorBrowsableState.Never)]
320 override public IEnumerator GetEnumerator() {
321 IEnumerator result = new DbEnumerator((IDataReader)this, true); // We always want to close the reader;
322 return result;
325 /// <summary>
326 /// implementation for DbDataReader.GetSchemaTable() method
327 ///
328 /// This is awaiting some common code
329 /// </summary>
330 /// <returns></returns>
331 /// <exception cref="NotSupportedException">GetSchemaTable is not supported at this time</exception>
332 override public DataTable GetSchemaTable() {
333 throw EntityUtil.NotSupported(System.Data.Entity.Strings.ADP_GetSchemaTableIsNotSupported);
336 /// <summary>
337 /// implementation for DbDataReader.NextResult() method
338 /// </summary>
339 /// <returns></returns>
340 override public bool NextResult() {
341 AssertReaderIsOpen("NextResult");
343 // If there is a next result set available, serve it.
344 if (NextResultShaperInfoEnumerator != null &&
345 Shaper.Reader.NextResult() &&
346 NextResultShaperInfoEnumerator.MoveNext())
348 Debug.Assert(DataRecord.Depth == 0, "Nested data readers should not have multiple result sets.");
349 var nextResultShaperInfo = NextResultShaperInfoEnumerator.Current;
350 DataRecord.CloseImplicitly();
351 SetShaper(nextResultShaperInfo.Key, nextResultShaperInfo.Value, depth: 0);
352 return true;
355 if (0 == DataRecord.Depth) {
356 // NOTE:: this is required to ensure that output parameter values
357 // are set in SQL Server, and other providers where they come after
358 // the results.
359 CommandHelper.ConsumeReader(Shaper.Reader);
361 else {
362 // For nested readers, make sure we're positioned properly for
363 // the following columns...
364 Consume();
367 // SQLBUDT #631726 - ensure we close the records that may be
368 // outstanding...
369 // SQLBUDT #632494 - do this after we consume the underlying reader
370 // so we don't run result assembly through it...
371 CloseImplicitly();
373 // Reset any state on our attached data record, since we've now
374 // gone past the end of the reader.
375 DataRecord.SetRecordSource(null, false);
377 return false;
380 /// <summary>
381 /// implementation for DbDataReader.Read() method
382 /// </summary>
383 /// <returns></returns>
384 override public bool Read() {
385 AssertReaderIsOpen("Read");
387 // First of all we need to inform each of the nested records that
388 // have been returned that they're "implicitly" closed -- that is
389 // we've moved on. This will also ensure that any records remaining
390 // in any active nested readers are consumed
391 DataRecord.CloseImplicitly();
393 // OK, now go ahead and advance the source enumerator and set the
394 // record source up
395 bool result = ReadInternal();
396 DataRecord.SetRecordSource(Shaper.RootEnumerator.Current, result);
397 return result;
400 /// <summary>
401 /// Internal read method; does the work of advancing the root enumerator
402 /// as needed and determining whether it's current record is for our
403 /// coordinator. The public Read method does the assertions and such that
404 /// we don't want to do when we're called from internal methods to do things
405 /// like consume the rest of the reader's contents.
406 /// </summary>
407 /// <param name="rootEnumerator"></param>
408 /// <returns></returns>
409 private bool ReadInternal() {
410 bool result = false;
412 // If there's nothing waiting for the root enumerator, then attempt
413 // to advance it.
414 if (!Shaper.DataWaiting) {
415 Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
418 // If we have some data (we may have just read it above) then figure
419 // out who it belongs to-- us or someone else. We also skip over any
420 // records that are for our children (nested readers); if we're being
421 // asked to read, it's too late for them to read them.
422 while (Shaper.DataWaiting
423 && Shaper.RootEnumerator.Current.CoordinatorFactory != CoordinatorFactory
424 && Shaper.RootEnumerator.Current.CoordinatorFactory.Depth > CoordinatorFactory.Depth) {
425 Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
428 if (Shaper.DataWaiting) {
429 // We found something, go ahead and indicate to the shaper we want
430 // this record, set up the data record, etc.
431 if (Shaper.RootEnumerator.Current.CoordinatorFactory == CoordinatorFactory) {
432 Shaper.DataWaiting = false;
433 Shaper.RootEnumerator.Current.AcceptPendingValues();
434 result = true;
437 return result;
440 #endregion
442 #region metadata properties and methods
444 /// <summary>
445 /// implementation for DbDataReader.DataRecordInfo property
446 /// </summary>
447 public DataRecordInfo DataRecordInfo {
448 get {
449 AssertReaderIsOpen("DataRecordInfo");
451 DataRecordInfo result;
452 if (DataRecord.HasData) {
453 result = DataRecord.DataRecordInfo;
455 else {
456 result = DefaultRecordState.DataRecordInfo;
458 return result;
462 /// <summary>
463 /// implementation for DbDataReader.FieldCount property
464 /// </summary>
465 override public int FieldCount {
466 get {
467 AssertReaderIsOpen("FieldCount");
469 // In this method, we need to return a constant value, regardless
470 // of how polymorphic the result is, because there is a lot of code
471 // in the wild that expects it to be constant; Ideally, we'd return
472 // the number of columns in the actual type that we have, but since
473 // that would probably break folks, I'm leaving it at returning the
474 // base set of columns that all rows will have.
476 int result = DefaultRecordState.ColumnCount;
477 return result;
481 /// <summary>
482 /// implementation for DbDataReader.GetDataTypeName() method
483 /// </summary>
484 /// <param name="ordinal"></param>
485 /// <returns></returns>
486 override public string GetDataTypeName(int ordinal) {
487 AssertReaderIsOpen("GetDataTypeName");
488 string result;
489 if (DataRecord.HasData) {
490 result = DataRecord.GetDataTypeName(ordinal);
492 else {
493 result = TypeHelpers.GetFullName(DefaultRecordState.GetTypeUsage(ordinal));
495 return result;
498 /// <summary>
499 /// implementation for DbDataReader.GetFieldType() method
500 /// </summary>
501 /// <param name="ordinal"></param>
502 /// <returns></returns>
503 override public Type GetFieldType(int ordinal) {
504 AssertReaderIsOpen("GetFieldType");
505 Type result;
506 if (DataRecord.HasData) {
507 result = DataRecord.GetFieldType(ordinal);
509 else {
510 result = GetClrTypeFromTypeMetadata(DefaultRecordState.GetTypeUsage(ordinal));
512 return result;
515 /// <summary>
516 /// implementation for DbDataReader.GetName() method
517 /// </summary>
518 /// <param name="ordinal"></param>
519 /// <returns></returns>
520 override public string GetName(int ordinal) {
521 AssertReaderIsOpen("GetName");
522 string result;
523 if (DataRecord.HasData) {
524 result = DataRecord.GetName(ordinal);
526 else {
527 result = DefaultRecordState.GetName(ordinal);
529 return result;
532 /// <summary>
533 /// implementation for DbDataReader.GetOrdinal() method
534 /// </summary>
535 /// <param name="name"></param>
536 /// <returns></returns>
538 override public int GetOrdinal(string name) {
539 AssertReaderIsOpen("GetOrdinal");
540 int result;
541 if (DataRecord.HasData) {
542 result = DataRecord.GetOrdinal(name);
544 else {
545 result = DefaultRecordState.GetOrdinal(name);
547 return result;
550 /// <summary>
551 /// implementation for DbDataReader.GetProviderSpecificFieldType() method
552 /// </summary>
553 /// <param name="ordinal"></param>
554 /// <returns></returns>
555 /// <exception cref="NotSupportedException">GetProviderSpecificFieldType is not supported at this time</exception>
556 [EditorBrowsableAttribute(EditorBrowsableState.Never)]
557 override public Type GetProviderSpecificFieldType(int ordinal) {
558 throw EntityUtil.NotSupported();
561 #endregion
563 #region data record properties and methods
565 ////////////////////////////////////////////////////////////////////////
566 ////////////////////////////////////////////////////////////////////////
567 ////////////////////////////////////////////////////////////////////////
569 // The remaining methods on this class delegate to the inner data record
571 ////////////////////////////////////////////////////////////////////////
572 ////////////////////////////////////////////////////////////////////////
573 ////////////////////////////////////////////////////////////////////////
575 #region general getter methods and indexer properties
577 /// <summary>
578 /// implementation for DbDataReader[ordinal] indexer value getter
579 /// </summary>
580 override public object this[int ordinal] {
581 get {
582 return DataRecord[ordinal];
586 /// <summary>
587 /// implementation for DbDataReader[name] indexer value getter
588 /// </summary>
589 override public object this[string name] {
590 get {
591 int ordinal = GetOrdinal(name);
592 return DataRecord[ordinal];
596 /// <summary>
597 /// implementation for DbDataReader.GetProviderSpecificValue() method
598 /// </summary>
599 /// <param name="ordinal"></param>
600 /// <returns></returns>
601 /// <exception cref="NotSupportedException">GetProviderSpecificValue is not supported at this time</exception>
602 [EditorBrowsableAttribute(EditorBrowsableState.Never)]
603 public override object GetProviderSpecificValue(int ordinal) {
604 throw EntityUtil.NotSupported();
607 /// <summary>
608 /// implementation for DbDataReader.GetProviderSpecificValues() method
609 /// </summary>
610 /// <param name="values"></param>
611 /// <returns></returns>
612 /// <exception cref="NotSupportedException">GetProviderSpecificValues is not supported at this time</exception>
613 [EditorBrowsableAttribute(EditorBrowsableState.Never)]
614 public override int GetProviderSpecificValues(object[] values) {
615 throw EntityUtil.NotSupported();
618 /// <summary>
619 /// implementation for DbDataReader.GetValue() method
620 /// </summary>
621 /// <param name="ordinal"></param>
622 /// <returns></returns>
623 override public Object GetValue(int ordinal) {
624 return DataRecord.GetValue(ordinal);
627 /// <summary>
628 /// implementation for DbDataReader.GetValues() method
629 /// </summary>
630 /// <param name="values"></param>
631 /// <returns></returns>
632 override public int GetValues(object[] values) {
633 return DataRecord.GetValues(values);
636 #endregion
638 #region simple scalar value getter methods
640 /// <summary>
641 /// implementation for DbDataReader.GetBoolean() method
642 /// </summary>
643 /// <param name="ordinal"></param>
644 /// <returns></returns>
645 override public bool GetBoolean(int ordinal) {
646 return DataRecord.GetBoolean(ordinal);
649 /// <summary>
650 /// implementation for DbDataReader.GetByte() method
651 /// </summary>
652 /// <param name="ordinal"></param>
653 /// <returns></returns>
654 override public byte GetByte(int ordinal) {
655 return DataRecord.GetByte(ordinal);
658 /// <summary>
659 /// implementation for DbDataReader.GetChar() method
660 /// </summary>
661 /// <param name="ordinal"></param>
662 /// <returns></returns>
663 override public char GetChar(int ordinal) {
664 return DataRecord.GetChar(ordinal);
667 /// <summary>
668 /// implementation for DbDataReader.GetDateTime() method
669 /// </summary>
670 /// <param name="ordinal"></param>
671 /// <returns></returns>
672 override public DateTime GetDateTime(int ordinal) {
673 return DataRecord.GetDateTime(ordinal);
676 /// <summary>
677 /// implementation for DbDataReader.GetDecimal() method
678 /// </summary>
679 /// <param name="ordinal"></param>
680 /// <returns></returns>
681 override public Decimal GetDecimal(int ordinal) {
682 return DataRecord.GetDecimal(ordinal);
685 /// <summary>
686 /// implementation for DbDataReader.GetDouble() method
687 /// </summary>
688 /// <param name="ordinal"></param>
689 /// <returns></returns>
690 override public double GetDouble(int ordinal) {
691 return DataRecord.GetDouble(ordinal);
694 /// <summary>
695 /// implementation for DbDataReader.GetFloat() method
696 /// </summary>
697 /// <param name="ordinal"></param>
698 /// <returns></returns>
699 override public float GetFloat(int ordinal) {
700 return DataRecord.GetFloat(ordinal);
703 /// <summary>
704 /// implementation for DbDataReader.GetGuid() method
705 /// </summary>
706 /// <param name="ordinal"></param>
707 /// <returns></returns>
708 override public Guid GetGuid(int ordinal) {
709 return DataRecord.GetGuid(ordinal);
712 /// <summary>
713 /// implementation for DbDataReader.GetInt16() method
714 /// </summary>
715 /// <param name="ordinal"></param>
716 /// <returns></returns>
717 override public Int16 GetInt16(int ordinal) {
718 return DataRecord.GetInt16(ordinal);
721 /// <summary>
722 /// implementation for DbDataReader.GetInt32() method
723 /// </summary>
724 /// <param name="ordinal"></param>
725 /// <returns></returns>
726 override public Int32 GetInt32(int ordinal) {
727 return DataRecord.GetInt32(ordinal);
730 /// <summary>
731 /// implementation for DbDataReader.GetInt64() method
732 /// </summary>
733 /// <param name="ordinal"></param>
734 /// <returns></returns>
735 override public Int64 GetInt64(int ordinal) {
736 return DataRecord.GetInt64(ordinal);
739 /// <summary>
740 /// implementation for DbDataReader.GetString() method
741 /// </summary>
742 /// <param name="ordinal"></param>
743 /// <returns></returns>
744 override public String GetString(int ordinal) {
745 return DataRecord.GetString(ordinal);
749 /// <summary>
750 /// implementation for DbDataReader.IsDBNull() method
751 /// </summary>
752 /// <param name="ordinal"></param>
753 /// <returns></returns>
754 override public bool IsDBNull(int ordinal) {
755 return DataRecord.IsDBNull(ordinal);
758 #endregion
760 #region array scalar value getter methods
762 /// <summary>
763 /// implementation for DbDataReader.GetBytes() method
764 /// </summary>
765 /// <param name="ordinal"></param>
766 /// <param name="dataOffset"></param>
767 /// <param name="buffer"></param>
768 /// <param name="bufferOffset"></param>
769 /// <param name="length"></param>
770 /// <returns></returns>
771 override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) {
772 return DataRecord.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
775 /// <summary>
776 /// implementation for DbDataReader.GetChars() method
777 /// </summary>
778 /// <param name="ordinal"></param>
779 /// <param name="dataOffset"></param>
780 /// <param name="buffer"></param>
781 /// <param name="bufferOffset"></param>
782 /// <param name="length"></param>
783 /// <returns></returns>
784 override public long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) {
785 return DataRecord.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);
788 #endregion
790 #region complex type getters
792 /// <summary>
793 /// implementation for DbDataReader.GetData() method
794 /// </summary>
795 /// <param name="ordinal"></param>
796 /// <returns></returns>
797 override protected DbDataReader GetDbDataReader(int ordinal) {
798 return (DbDataReader)DataRecord.GetData(ordinal);
801 /// <summary>
802 /// implementation for DbDataReader.GetDataRecord() method
803 /// </summary>
804 /// <param name="ordinal"></param>
805 /// <returns></returns>
806 public DbDataRecord GetDataRecord(int ordinal) {
807 return DataRecord.GetDataRecord(ordinal);
810 /// <summary>
811 /// Used to return a nested result
812 /// </summary>
813 /// <param name="ordinal"></param>
814 /// <returns></returns>
815 public DbDataReader GetDataReader(int ordinal) {
816 return this.GetDbDataReader(ordinal);
819 #endregion
821 #endregion