File: BridgeDataReader.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (823 lines) | stat: -rw-r--r-- 32,188 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
//------------------------------------------------------------------------------
// <copyright file="BridgeDataReader.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

namespace System.Data.Query.ResultAssembly {

    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.Common;
    using System.Data.Common.Internal.Materialization;
    using System.Data.Common.Utils;
    using System.Data.Metadata.Edm;
    using System.Data.Query.InternalTrees;
    using System.Data.Query.PlanCompiler;
    using System.Diagnostics;

    /// <summary>
    /// DbDataReader functionality for the bridge.
    /// </summary>
    internal sealed class BridgeDataReader : DbDataReader, IExtendedDataRecord {

        #region private state

        /// <summary>
        /// Object that holds the state needed by the coordinator and the root enumerator
        /// </summary>
        private Shaper<RecordState> Shaper;

        /// <summary>
        /// Enumerator over shapers for NextResult() calls. 
        /// Null for nested data readers (depth > 0);
        /// </summary>
        private IEnumerator<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> NextResultShaperInfoEnumerator;

        /// <summary>
        /// The coordinator we're responsible for returning results for.
        /// </summary>
        private CoordinatorFactory<RecordState> CoordinatorFactory;

        /// <summary>
        /// The default record (pre-read/past-end) state
        /// </summary>
        private RecordState DefaultRecordState;

        /// <summary>
        /// We delegate to this on our getters, to avoid duplicate code.
        /// </summary>
        private BridgeDataRecord DataRecord;

        /// <summary>
        /// Do we have a row to read?  Determined in the constructor and
        /// should not be changed.
        /// </summary>
        private bool _hasRows;

        /// <summary>
        /// Set to true only when we've been closed through the Close() method
        /// </summary>
        private bool _isClosed;

        #endregion

        #region constructors

        /// <summary>
        /// Constructor used by the ResultColumn when doing GetValue, and by the Create factory
        /// method.
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="isRoot"></param>
        /// <param name="nextResultShaperInfos">enumrator of the shapers for NextResult() calls</param>
        internal BridgeDataReader(Shaper<RecordState> shaper, CoordinatorFactory<RecordState> coordinatorFactory, int depth, IEnumerator<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> nextResultShaperInfos)
            : base() {
            Debug.Assert(null != shaper, "null shaper?");
            Debug.Assert(null != coordinatorFactory, "null coordinatorFactory?");
            Debug.Assert(depth == 0 || nextResultShaperInfos == null, "Nested data readers should not have multiple result sets.");

            NextResultShaperInfoEnumerator = nextResultShaperInfos != null ? nextResultShaperInfos : null;
            SetShaper(shaper, coordinatorFactory, depth);
        }

        private void SetShaper(Shaper<RecordState> shaper, CoordinatorFactory<RecordState> coordinatorFactory, int depth)
        {
            Shaper = shaper;
            CoordinatorFactory = coordinatorFactory;
            DataRecord = new BridgeDataRecord(shaper, depth);

            // To determine whether there are any rows for this coordinator at this place in 
            // the root enumerator, we pretty much just look at it's current record (we'll read 
            // one if there isn't one waiting) and if it matches our coordinator, we've got rows.
            _hasRows = false;

            if (!Shaper.DataWaiting) {
                Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
            }
            if (Shaper.DataWaiting) {
                RecordState currentRecord = Shaper.RootEnumerator.Current;

                if (null != currentRecord) {
                    _hasRows = (currentRecord.CoordinatorFactory == CoordinatorFactory);
                }
            }

            // Once we've created the root enumerator, we can get the default record state
            DefaultRecordState = coordinatorFactory.GetDefaultRecordState(Shaper);
            Debug.Assert(null != DefaultRecordState, "no default?");
        }

        /// <summary>
        /// The primary factory method to produce the BridgeDataReader; given a store data 
        /// reader and a column map, create the BridgeDataReader, hooking up the IteratorSources  
        /// and ResultColumn Hierarchy.  All construction of top level data readers go through
        /// this method.
        /// </summary>
        /// <param name="storeDataReader"></param>
        /// <param name="columnMap">column map of the first result set</param>
        /// <param name="nextResultColumnMaps">enumerable of the column maps for NextResult() calls.</param>
        /// <returns></returns>
        static internal DbDataReader Create(DbDataReader storeDataReader, ColumnMap columnMap, MetadataWorkspace workspace, IEnumerable<ColumnMap> nextResultColumnMaps) {
            Debug.Assert(storeDataReader != null, "null storeDataReaders?");
            Debug.Assert(columnMap != null, "null columnMap?");
            Debug.Assert(workspace != null, "null workspace?");

            var shaperInfo = CreateShaperInfo(storeDataReader, columnMap, workspace);
            DbDataReader result = new BridgeDataReader(shaperInfo.Key, shaperInfo.Value, /*depth:*/ 0, GetNextResultShaperInfo(storeDataReader, workspace, nextResultColumnMaps).GetEnumerator());
            return result;
        }

        private static KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>> CreateShaperInfo(DbDataReader storeDataReader, ColumnMap columnMap, MetadataWorkspace workspace)
        {
            Debug.Assert(storeDataReader != null, "null storeDataReaders?");
            Debug.Assert(columnMap != null, "null columnMap?");
            Debug.Assert(workspace != null, "null workspace?");

            System.Data.Common.QueryCache.QueryCacheManager cacheManager = workspace.GetQueryCacheManager();
            const System.Data.Objects.MergeOption NoTracking = System.Data.Objects.MergeOption.NoTracking;

            ShaperFactory<RecordState> shaperFactory = Translator.TranslateColumnMap<RecordState>(cacheManager, columnMap, workspace, null, NoTracking, true);
            Shaper<RecordState> recordShaper = shaperFactory.Create(storeDataReader, null, workspace, System.Data.Objects.MergeOption.NoTracking, true);

            return new KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>(recordShaper, recordShaper.RootCoordinator.TypedCoordinatorFactory);
        }

        private static IEnumerable<KeyValuePair<Shaper<RecordState>, CoordinatorFactory<RecordState>>> GetNextResultShaperInfo(DbDataReader storeDataReader, MetadataWorkspace workspace, IEnumerable<ColumnMap> nextResultColumnMaps)
        {
            foreach (var nextResultColumnMap in nextResultColumnMaps)
            {
                yield return CreateShaperInfo(storeDataReader, nextResultColumnMap, workspace);
            }
        }

        #endregion

        #region helpers

        /// <summary>
        /// Implicitly close this (nested) data reader; will be called whenever 
        /// the user has done a GetValue() or a Read() on a parent reader/record
        /// to ensure that we consume all our results.  We do that because we 
        /// our design requires us to be positioned at the next nested reader's
        /// first row.
        /// </summary>
        internal void CloseImplicitly() {
            Consume();
            DataRecord.CloseImplicitly();
        }

        /// <summary>
        /// Reads to the end of the source enumerator provided
        /// </summary>
        private void Consume() {
            while (ReadInternal()) ;
        }

        /// <summary>
        /// Figure out the CLR type from the TypeMetadata object; For scalars, 
        /// we can get this from the metadata workspace, but for the rest, we 
        /// just guess at "Object".  You need to use the DataRecordInfo property 
        /// to get better information for those.
        /// </summary>
        /// <param name="typeUsage"></param>
        /// <returns></returns>
        internal static Type GetClrTypeFromTypeMetadata(TypeUsage typeUsage) {
            Type result;

            PrimitiveType primitiveType;
            if (TypeHelpers.TryGetEdmType<PrimitiveType>(typeUsage, out primitiveType)) {
                result = primitiveType.ClrEquivalentType;
            }
            else {
                if (TypeSemantics.IsReferenceType(typeUsage)) {
                    result = typeof(EntityKey);
                }
                else if (TypeUtils.IsStructuredType(typeUsage)) {
                    result = typeof(DbDataRecord);
                }
                else if (TypeUtils.IsCollectionType(typeUsage)) {
                    result = typeof(DbDataReader);
                }
                else if (TypeUtils.IsEnumerationType(typeUsage)) {
                    result = ((EnumType)typeUsage.EdmType).UnderlyingType.ClrEquivalentType;
                }
                else {
                    result = typeof(object);
                }
            }
            return result;
        }

        #endregion

        #region data reader specific properties and methods

        /// <summary>
        /// implementation for DbDataReader.Depth property
        /// </summary>
        override public int Depth {
            get {
                AssertReaderIsOpen("Depth");
                return DataRecord.Depth;
            }
        }

        /// <summary>
        /// implementation for DbDataReader.HasRows property
        /// </summary>
        override public bool HasRows {
            get {
                AssertReaderIsOpen("HasRows");
                return _hasRows;
            }
        }

        /// <summary>
        /// implementation for DbDataReader.IsClosed property
        /// </summary>        
        override public bool IsClosed {
            get {
                // Rather that try and track this in two places; we just delegate
                // to the data record that we constructed; it has more reasons to 
                // have to know this than we do in the data reader.  (Of course, 
                // we look at our own closed state too...)
                return ((_isClosed) || DataRecord.IsClosed);
            }
        }

        /// <summary>
        /// implementation for DbDataReader.RecordsAffected property
        /// </summary>        
        override public int RecordsAffected {
            get {
                int result = -1; // For nested readers, return -1 which is the default for queries.

                // We defer to the store reader for rows affected count. Note that for queries,
                // the provider is generally expected to return -1.
                // 
                if (DataRecord.Depth == 0) {
                    result = Shaper.Reader.RecordsAffected;
                }
                return result;
            }
        }

        /// <summary>
        /// Ensures that the reader is actually open, and throws an exception if not
        /// </summary>
        private void AssertReaderIsOpen(string methodName) {
            if (IsClosed) {
                if (DataRecord.IsImplicitlyClosed) {
                    throw EntityUtil.ImplicitlyClosedDataReaderError();
                }
                if (DataRecord.IsExplicitlyClosed) {
                    throw EntityUtil.DataReaderClosed(methodName);
                }
            }
        }

        /// <summary>
        /// implementation for DbDataReader.Close() method
        /// </summary>
        override public void Close() {
            // Make sure we explicitly closed the data record, since that's what
            // where using to track closed state.
            DataRecord.CloseExplicitly();

            if (!_isClosed) {
                _isClosed = true;

                if (0 == DataRecord.Depth) {
                    // If we're the root collection, we want to ensure the remainder of
                    // the result column hierarchy is closed out, to avoid dangling
                    // references to it, should it be reused. We also want to physically 
                    // close out the source reader as well.
                    Shaper.Reader.Close();
                }
                else {
                    // For non-root collections, we have to consume all the data, or we'll
                    // not be positioned propertly for what comes afterward.
                    Consume();
                }
            }

            if (NextResultShaperInfoEnumerator != null)
            {
                NextResultShaperInfoEnumerator.Dispose();
                NextResultShaperInfoEnumerator = null;
            }
        }

        /// <summary>
        /// implementation for DbDataReader.GetEnumerator() method
        /// </summary>
        [EditorBrowsableAttribute(EditorBrowsableState.Never)]
        override public IEnumerator GetEnumerator() {
            IEnumerator result = new DbEnumerator((IDataReader)this, true); // We always want to close the reader; 
            return result;
        }

        /// <summary>
        /// implementation for DbDataReader.GetSchemaTable() method
        /// 
        /// This is awaiting some common code
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">GetSchemaTable is not supported at this time</exception>
        override public DataTable GetSchemaTable() {
            throw EntityUtil.NotSupported(System.Data.Entity.Strings.ADP_GetSchemaTableIsNotSupported);
        }

        /// <summary>
        /// implementation for DbDataReader.NextResult() method
        /// </summary>
        /// <returns></returns>
        override public bool NextResult() {
            AssertReaderIsOpen("NextResult");

            // If there is a next result set available, serve it.
            if (NextResultShaperInfoEnumerator != null && 
                Shaper.Reader.NextResult() &&
                NextResultShaperInfoEnumerator.MoveNext())
            {
                Debug.Assert(DataRecord.Depth == 0, "Nested data readers should not have multiple result sets.");
                var nextResultShaperInfo = NextResultShaperInfoEnumerator.Current;
                DataRecord.CloseImplicitly();
                SetShaper(nextResultShaperInfo.Key, nextResultShaperInfo.Value, depth: 0);
                return true;
            }

            if (0 == DataRecord.Depth) {
                // NOTE:: this is required to ensure that output parameter values 
                // are set in SQL Server, and other providers where they come after
                // the results.
                CommandHelper.ConsumeReader(Shaper.Reader);
            }
            else {
                // For nested readers, make sure we're positioned properly for 
                // the following columns...
                Consume();
            }

            // SQLBUDT #631726 - ensure we close the records that may be 
            // outstanding...
            // SQLBUDT #632494 - do this after we consume the underlying reader 
            // so we don't run result assembly through it...
            CloseImplicitly();

            // Reset any state on our attached data record, since we've now
            // gone past the end of the reader.
            DataRecord.SetRecordSource(null, false);

            return false;
        }

        /// <summary>
        /// implementation for DbDataReader.Read() method
        /// </summary>
        /// <returns></returns>
        override public bool Read() {
            AssertReaderIsOpen("Read");

            // First of all we need to inform each of the nested records that
            // have been returned that they're "implicitly" closed -- that is 
            // we've moved on.  This will also ensure that any records remaining
            // in any active nested readers are consumed
            DataRecord.CloseImplicitly();

            // OK, now go ahead and advance the source enumerator and set the 
            // record source up 
            bool result = ReadInternal();
            DataRecord.SetRecordSource(Shaper.RootEnumerator.Current, result);
            return result;
        }

        /// <summary>
        /// Internal read method; does the work of advancing the root enumerator
        /// as needed and determining whether it's current record is for our
        /// coordinator.  The public Read method does the assertions and such that
        /// we don't want to do when we're called from internal methods to do things
        /// like consume the rest of the reader's contents.
        /// </summary>
        /// <param name="rootEnumerator"></param>
        /// <returns></returns>
        private bool ReadInternal() {
            bool result = false;

            // If there's nothing waiting for the root enumerator, then attempt
            // to advance it. 
            if (!Shaper.DataWaiting) {
                Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
            }

            // If we have some data (we may have just read it above) then figure
            // out who it belongs to-- us or someone else. We also skip over any
            // records that are for our children (nested readers); if we're being
            // asked to read, it's too late for them to read them.
            while (Shaper.DataWaiting
                        && Shaper.RootEnumerator.Current.CoordinatorFactory != CoordinatorFactory
                        && Shaper.RootEnumerator.Current.CoordinatorFactory.Depth > CoordinatorFactory.Depth) {
                Shaper.DataWaiting = Shaper.RootEnumerator.MoveNext();
            }

            if (Shaper.DataWaiting) {
                // We found something, go ahead and indicate to the shaper we want 
                // this record, set up the data record, etc.
                if (Shaper.RootEnumerator.Current.CoordinatorFactory == CoordinatorFactory) {
                    Shaper.DataWaiting = false;
                    Shaper.RootEnumerator.Current.AcceptPendingValues();
                    result = true;
                }
            }
            return result;
        }

        #endregion

        #region metadata properties and methods

        /// <summary>
        /// implementation for DbDataReader.DataRecordInfo property
        /// </summary>
        public DataRecordInfo DataRecordInfo {
            get {
                AssertReaderIsOpen("DataRecordInfo");

                DataRecordInfo result;
                if (DataRecord.HasData) {
                    result = DataRecord.DataRecordInfo;
                }
                else {
                    result = DefaultRecordState.DataRecordInfo;
                }
                return result;
            }
        }

        /// <summary>
        /// implementation for DbDataReader.FieldCount property
        /// </summary>
        override public int FieldCount {
            get {
                AssertReaderIsOpen("FieldCount");

                // In this method, we need to return a constant value, regardless
                // of how polymorphic the result is, because there is a lot of code
                // in the wild that expects it to be constant; Ideally, we'd return
                // the number of columns in the actual type that we have, but since
                // that would probably break folks, I'm leaving it at returning the
                // base set of columns that all rows will have.

                int result = DefaultRecordState.ColumnCount;
                return result;
            }
        }

        /// <summary>
        /// implementation for DbDataReader.GetDataTypeName() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public string GetDataTypeName(int ordinal) {
            AssertReaderIsOpen("GetDataTypeName");
            string result;
            if (DataRecord.HasData) {
                result = DataRecord.GetDataTypeName(ordinal);
            }
            else {
                result = TypeHelpers.GetFullName(DefaultRecordState.GetTypeUsage(ordinal));
            }
            return result;
        }

        /// <summary>
        /// implementation for DbDataReader.GetFieldType() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Type GetFieldType(int ordinal) {
            AssertReaderIsOpen("GetFieldType");
            Type result;
            if (DataRecord.HasData) {
                result = DataRecord.GetFieldType(ordinal);
            }
            else {
                result = GetClrTypeFromTypeMetadata(DefaultRecordState.GetTypeUsage(ordinal));
            }
            return result;
        }

        /// <summary>
        /// implementation for DbDataReader.GetName() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public string GetName(int ordinal) {
            AssertReaderIsOpen("GetName");
            string result;
            if (DataRecord.HasData) {
                result = DataRecord.GetName(ordinal);
            }
            else {
                result = DefaultRecordState.GetName(ordinal);
            }
            return result;
        }

        /// <summary>
        /// implementation for DbDataReader.GetOrdinal() method
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>

        override public int GetOrdinal(string name) {
            AssertReaderIsOpen("GetOrdinal");
            int result;
            if (DataRecord.HasData) {
                result = DataRecord.GetOrdinal(name);
            }
            else {
                result = DefaultRecordState.GetOrdinal(name);
            }
            return result;
        }

        /// <summary>
        /// implementation for DbDataReader.GetProviderSpecificFieldType() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">GetProviderSpecificFieldType is not supported at this time</exception>
        [EditorBrowsableAttribute(EditorBrowsableState.Never)]
        override public Type GetProviderSpecificFieldType(int ordinal) {
            throw EntityUtil.NotSupported();
        }

        #endregion

        #region data record properties and methods

        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        //
        // The remaining methods on this class delegate to the inner data record
        //
        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////

        #region general getter methods and indexer properties

        /// <summary>
        /// implementation for DbDataReader[ordinal] indexer value getter
        /// </summary>
        override public object this[int ordinal] {
            get {
                return DataRecord[ordinal];
            }
        }

        /// <summary>
        /// implementation for DbDataReader[name] indexer value getter
        /// </summary>
        override public object this[string name] {
            get {
                int ordinal = GetOrdinal(name);
                return DataRecord[ordinal];
            }
        }

        /// <summary>
        /// implementation for DbDataReader.GetProviderSpecificValue() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">GetProviderSpecificValue is not supported at this time</exception>
        [EditorBrowsableAttribute(EditorBrowsableState.Never)]
        public override object GetProviderSpecificValue(int ordinal) {
            throw EntityUtil.NotSupported();
        }

        /// <summary>
        /// implementation for DbDataReader.GetProviderSpecificValues() method
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">GetProviderSpecificValues is not supported at this time</exception>
        [EditorBrowsableAttribute(EditorBrowsableState.Never)]
        public override int GetProviderSpecificValues(object[] values) {
            throw EntityUtil.NotSupported();
        }

        /// <summary>
        /// implementation for DbDataReader.GetValue() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Object GetValue(int ordinal) {
            return DataRecord.GetValue(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetValues() method
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        override public int GetValues(object[] values) {
            return DataRecord.GetValues(values);
        }

        #endregion

        #region simple scalar value getter methods

        /// <summary>
        /// implementation for DbDataReader.GetBoolean() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public bool GetBoolean(int ordinal) {
            return DataRecord.GetBoolean(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetByte() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public byte GetByte(int ordinal) {
            return DataRecord.GetByte(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetChar() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public char GetChar(int ordinal) {
            return DataRecord.GetChar(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetDateTime() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public DateTime GetDateTime(int ordinal) {
            return DataRecord.GetDateTime(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetDecimal() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Decimal GetDecimal(int ordinal) {
            return DataRecord.GetDecimal(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetDouble() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public double GetDouble(int ordinal) {
            return DataRecord.GetDouble(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetFloat() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public float GetFloat(int ordinal) {
            return DataRecord.GetFloat(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetGuid() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Guid GetGuid(int ordinal) {
            return DataRecord.GetGuid(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetInt16() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Int16 GetInt16(int ordinal) {
            return DataRecord.GetInt16(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetInt32() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Int32 GetInt32(int ordinal) {
            return DataRecord.GetInt32(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetInt64() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public Int64 GetInt64(int ordinal) {
            return DataRecord.GetInt64(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetString() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public String GetString(int ordinal) {
            return DataRecord.GetString(ordinal);
        }


        /// <summary>
        /// implementation for DbDataReader.IsDBNull() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override public bool IsDBNull(int ordinal) {
            return DataRecord.IsDBNull(ordinal);
        }

        #endregion

        #region array scalar value getter methods

        /// <summary>
        /// implementation for DbDataReader.GetBytes() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <param name="dataOffset"></param>
        /// <param name="buffer"></param>
        /// <param name="bufferOffset"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) {
            return DataRecord.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
        }

        /// <summary>
        /// implementation for DbDataReader.GetChars() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <param name="dataOffset"></param>
        /// <param name="buffer"></param>
        /// <param name="bufferOffset"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        override public long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) {
            return DataRecord.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);
        }

        #endregion

        #region complex type getters

        /// <summary>
        /// implementation for DbDataReader.GetData() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        override protected DbDataReader GetDbDataReader(int ordinal) {
            return (DbDataReader)DataRecord.GetData(ordinal);
        }

        /// <summary>
        /// implementation for DbDataReader.GetDataRecord() method
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        public DbDataRecord GetDataRecord(int ordinal) {
            return DataRecord.GetDataRecord(ordinal);
        }

        /// <summary>
        /// Used to return a nested result
        /// </summary>
        /// <param name="ordinal"></param>
        /// <returns></returns>
        public DbDataReader GetDataReader(int ordinal) {
            return this.GetDbDataReader(ordinal);
        }

        #endregion

        #endregion
    }
}