Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Query / ResultAssembly / BridgeDataReader.cs / 1 / BridgeDataReader.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// @owner [....], [....]
//---------------------------------------------------------------------
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.CommandTrees;
using System.Data.Common.Internal.Materialization;
using System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
using System.Data.Query.PlanCompiler;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Data.Entity;
using System.Linq;
using System.Data.Mapping;
using System.Data.Common.Utils;
///
/// DbDataReader functionality for the bridge.
///
internal sealed class BridgeDataReader : DbDataReader, IExtendedDataRecord {
#region private state
///
/// Object that holds the state needed by the coordinator and the root enumerator
///
private readonly Shaper Shaper;
///
/// The coordinator we're responsible for returning results for.
///
private readonly CoordinatorFactory CoordinatorFactory;
///
/// The default record (pre-read/past-end) state
///
private readonly RecordState DefaultRecordState;
///
/// We delegate to this on our getters, to avoid duplicate code.
///
private readonly BridgeDataRecord DataRecord;
///
/// Do we have a row to read? Determined in the constructor and
/// should not be changed.
///
private readonly bool _hasRows;
///
/// Set to true only when we've been closed through the Close() method
///
private bool _isClosed;
#endregion
#region constructors
///
/// Constructor used by the ResultColumn when doing GetValue, and by the Create factory
/// method.
///
///
///
internal BridgeDataReader(Shaper shaper, CoordinatorFactory coordinatorFactory, int depth)
: base() {
Debug.Assert(null != shaper, "null shaper?");
Debug.Assert(null != coordinatorFactory, "null coordinatorFactory?");
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?");
}
///
/// 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.
///
///
///
///
static internal DbDataReader Create(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 shaperFactory = Translator.TranslateColumnMap(cacheManager, columnMap, workspace, null, NoTracking, true);
Shaper recordShaper = shaperFactory.Create(storeDataReader, workspace);
DbDataReader result = new BridgeDataReader(recordShaper, recordShaper.RootCoordinator.TypedCoordinatorFactory, 0);
return result;
}
#endregion
#region helpers
///
/// 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.
///
internal void CloseImplicitly() {
Consume();
DataRecord.CloseImplicitly();
}
///
/// Reads to the end of the source enumerator provided
///
private void Consume() {
while (ReadInternal()) ;
}
///
/// 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.
///
///
///
internal static Type GetClrTypeFromTypeMetadata(TypeUsage typeUsage) {
Type result;
PrimitiveType primitiveType;
if (TypeHelpers.TryGetEdmType(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 {
result = typeof(object);
}
}
return result;
}
#endregion
#region data reader specific properties and methods
///
/// implementation for DbDataReader.Depth property
///
override public int Depth {
get {
AssertReaderIsOpen("Depth");
return DataRecord.Depth;
}
}
///
/// implementation for DbDataReader.HasRows property
///
override public bool HasRows {
get {
AssertReaderIsOpen("HasRows");
return _hasRows;
}
}
///
/// implementation for DbDataReader.IsClosed property
///
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);
}
}
///
/// implementation for DbDataReader.RecordsAffected property
///
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;
}
}
///
/// Ensures that the reader is actually open, and throws an exception if not
///
private void AssertReaderIsOpen(string methodName) {
if (IsClosed) {
if (DataRecord.IsImplicitlyClosed) {
throw EntityUtil.ImplicitlyClosedDataReaderError();
}
if (DataRecord.IsExplicitlyClosed) {
throw EntityUtil.DataReaderClosed(methodName);
}
}
}
///
/// implementation for DbDataReader.Close() method
///
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();
}
}
}
///
/// implementation for DbDataReader.GetEnumerator() method
///
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
override public IEnumerator GetEnumerator() {
IEnumerator result = new DbEnumerator((IDataReader)this, true); // We always want to close the reader;
return result;
}
///
/// implementation for DbDataReader.GetSchemaTable() method
///
/// This is awaiting some common code
///
///
/// GetSchemaTable is not supported at this time
override public DataTable GetSchemaTable() {
throw EntityUtil.NotSupported(System.Data.Entity.Strings.ADP_GetSchemaTableIsNotSupported);
}
///
/// implementation for DbDataReader.NextResult() method
///
/// since the bridge currently doesn't support multiple results in a
/// single command, this always returns false.
///
///
override public bool NextResult() {
AssertReaderIsOpen("NextResult");
// SQLBUDT #631726 - ensure we close the records that may be
// outstanding...
CloseImplicitly();
// Consume results in the source collection to ensure that the
// store reader and the bridge data reader are in the same state.
// If we are not a root reader, we do not 'own' the store reader
// and do nothing.
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();
}
// Reset any state on our attached data record, since we've now
// gone past the end of the reader.
DataRecord.SetRecordSource(null, false);
// NOTE: if the bridge ever supports multiple results in a single
// command, we'll need to change this, but for now we can't
// ever have another result.
return false;
}
///
/// implementation for DbDataReader.Read() method
///
///
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;
}
///
/// 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.
///
///
///
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
///
/// implementation for DbDataReader.DataRecordInfo property
///
public DataRecordInfo DataRecordInfo {
get {
AssertReaderIsOpen("DataRecordInfo");
DataRecordInfo result;
if (DataRecord.HasData) {
result = DataRecord.DataRecordInfo;
}
else {
result = DefaultRecordState.DataRecordInfo;
}
return result;
}
}
///
/// implementation for DbDataReader.FieldCount property
///
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;
}
}
///
/// implementation for DbDataReader.GetDataTypeName() method
///
///
///
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;
}
///
/// implementation for DbDataReader.GetFieldType() method
///
///
///
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;
}
///
/// implementation for DbDataReader.GetName() method
///
///
///
override public string GetName(int ordinal) {
AssertReaderIsOpen("GetName");
string result;
if (DataRecord.HasData) {
result = DataRecord.GetName(ordinal);
}
else {
result = DefaultRecordState.GetName(ordinal);
}
return result;
}
///
/// implementation for DbDataReader.GetOrdinal() method
///
///
///
override public int GetOrdinal(string name) {
AssertReaderIsOpen("GetOrdinal");
int result;
if (DataRecord.HasData) {
result = DataRecord.GetOrdinal(name);
}
else {
result = DefaultRecordState.GetOrdinal(name);
}
return result;
}
///
/// implementation for DbDataReader.GetProviderSpecificFieldType() method
///
///
///
/// GetProviderSpecificFieldType is not supported at this time
[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
///
/// implementation for DbDataReader[ordinal] indexer value getter
///
override public object this[int ordinal] {
get {
return DataRecord[ordinal];
}
}
///
/// implementation for DbDataReader[name] indexer value getter
///
override public object this[string name] {
get {
int ordinal = GetOrdinal(name);
return DataRecord[ordinal];
}
}
///
/// implementation for DbDataReader.GetProviderSpecificValue() method
///
///
///
/// GetProviderSpecificValue is not supported at this time
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public override object GetProviderSpecificValue(int ordinal) {
throw EntityUtil.NotSupported();
}
///
/// implementation for DbDataReader.GetProviderSpecificValues() method
///
///
///
/// GetProviderSpecificValues is not supported at this time
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public override int GetProviderSpecificValues(object[] values) {
throw EntityUtil.NotSupported();
}
///
/// implementation for DbDataReader.GetValue() method
///
///
///
override public Object GetValue(int ordinal) {
return DataRecord.GetValue(ordinal);
}
///
/// implementation for DbDataReader.GetValues() method
///
///
///
override public int GetValues(object[] values) {
return DataRecord.GetValues(values);
}
#endregion
#region simple scalar value getter methods
///
/// implementation for DbDataReader.GetBoolean() method
///
///
///
override public bool GetBoolean(int ordinal) {
return DataRecord.GetBoolean(ordinal);
}
///
/// implementation for DbDataReader.GetByte() method
///
///
///
override public byte GetByte(int ordinal) {
return DataRecord.GetByte(ordinal);
}
///
/// implementation for DbDataReader.GetChar() method
///
///
///
override public char GetChar(int ordinal) {
return DataRecord.GetChar(ordinal);
}
///
/// implementation for DbDataReader.GetDateTime() method
///
///
///
override public DateTime GetDateTime(int ordinal) {
return DataRecord.GetDateTime(ordinal);
}
///
/// implementation for DbDataReader.GetDecimal() method
///
///
///
override public Decimal GetDecimal(int ordinal) {
return DataRecord.GetDecimal(ordinal);
}
///
/// implementation for DbDataReader.GetDouble() method
///
///
///
override public double GetDouble(int ordinal) {
return DataRecord.GetDouble(ordinal);
}
///
/// implementation for DbDataReader.GetFloat() method
///
///
///
override public float GetFloat(int ordinal) {
return DataRecord.GetFloat(ordinal);
}
///
/// implementation for DbDataReader.GetGuid() method
///
///
///
override public Guid GetGuid(int ordinal) {
return DataRecord.GetGuid(ordinal);
}
///
/// implementation for DbDataReader.GetInt16() method
///
///
///
override public Int16 GetInt16(int ordinal) {
return DataRecord.GetInt16(ordinal);
}
///
/// implementation for DbDataReader.GetInt32() method
///
///
///
override public Int32 GetInt32(int ordinal) {
return DataRecord.GetInt32(ordinal);
}
///
/// implementation for DbDataReader.GetInt64() method
///
///
///
override public Int64 GetInt64(int ordinal) {
return DataRecord.GetInt64(ordinal);
}
///
/// implementation for DbDataReader.GetString() method
///
///
///
override public String GetString(int ordinal) {
return DataRecord.GetString(ordinal);
}
///
/// implementation for DbDataReader.IsDBNull() method
///
///
///
override public bool IsDBNull(int ordinal) {
return DataRecord.IsDBNull(ordinal);
}
#endregion
#region chunking scalar value getter methods
///
/// implementation for DbDataReader.GetBytes() method
///
///
///
///
///
///
///
override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) {
return DataRecord.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
}
///
/// implementation for DbDataReader.GetChars() method
///
///
///
///
///
///
///
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
///
/// implementation for DbDataReader.GetData() method
///
///
///
override protected DbDataReader GetDbDataReader(int ordinal) {
return (DbDataReader)DataRecord.GetData(ordinal);
}
///
/// implementation for DbDataReader.GetDataRecord() method
///
///
///
public DbDataRecord GetDataRecord(int ordinal) {
return DataRecord.GetDataRecord(ordinal);
}
///
/// Used to return a nested result
///
///
///
public DbDataReader GetDataReader(int ordinal) {
return this.GetDbDataReader(ordinal);
}
#endregion
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// @owner [....], [....]
//---------------------------------------------------------------------
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.CommandTrees;
using System.Data.Common.Internal.Materialization;
using System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
using System.Data.Query.PlanCompiler;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Data.Entity;
using System.Linq;
using System.Data.Mapping;
using System.Data.Common.Utils;
///
/// DbDataReader functionality for the bridge.
///
internal sealed class BridgeDataReader : DbDataReader, IExtendedDataRecord {
#region private state
///
/// Object that holds the state needed by the coordinator and the root enumerator
///
private readonly Shaper Shaper;
///
/// The coordinator we're responsible for returning results for.
///
private readonly CoordinatorFactory CoordinatorFactory;
///
/// The default record (pre-read/past-end) state
///
private readonly RecordState DefaultRecordState;
///
/// We delegate to this on our getters, to avoid duplicate code.
///
private readonly BridgeDataRecord DataRecord;
///
/// Do we have a row to read? Determined in the constructor and
/// should not be changed.
///
private readonly bool _hasRows;
///
/// Set to true only when we've been closed through the Close() method
///
private bool _isClosed;
#endregion
#region constructors
///
/// Constructor used by the ResultColumn when doing GetValue, and by the Create factory
/// method.
///
///
///
internal BridgeDataReader(Shaper shaper, CoordinatorFactory coordinatorFactory, int depth)
: base() {
Debug.Assert(null != shaper, "null shaper?");
Debug.Assert(null != coordinatorFactory, "null coordinatorFactory?");
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?");
}
///
/// 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.
///
///
///
///
static internal DbDataReader Create(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 shaperFactory = Translator.TranslateColumnMap(cacheManager, columnMap, workspace, null, NoTracking, true);
Shaper recordShaper = shaperFactory.Create(storeDataReader, workspace);
DbDataReader result = new BridgeDataReader(recordShaper, recordShaper.RootCoordinator.TypedCoordinatorFactory, 0);
return result;
}
#endregion
#region helpers
///
/// 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.
///
internal void CloseImplicitly() {
Consume();
DataRecord.CloseImplicitly();
}
///
/// Reads to the end of the source enumerator provided
///
private void Consume() {
while (ReadInternal()) ;
}
///
/// 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.
///
///
///
internal static Type GetClrTypeFromTypeMetadata(TypeUsage typeUsage) {
Type result;
PrimitiveType primitiveType;
if (TypeHelpers.TryGetEdmType(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 {
result = typeof(object);
}
}
return result;
}
#endregion
#region data reader specific properties and methods
///
/// implementation for DbDataReader.Depth property
///
override public int Depth {
get {
AssertReaderIsOpen("Depth");
return DataRecord.Depth;
}
}
///
/// implementation for DbDataReader.HasRows property
///
override public bool HasRows {
get {
AssertReaderIsOpen("HasRows");
return _hasRows;
}
}
///
/// implementation for DbDataReader.IsClosed property
///
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);
}
}
///
/// implementation for DbDataReader.RecordsAffected property
///
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;
}
}
///
/// Ensures that the reader is actually open, and throws an exception if not
///
private void AssertReaderIsOpen(string methodName) {
if (IsClosed) {
if (DataRecord.IsImplicitlyClosed) {
throw EntityUtil.ImplicitlyClosedDataReaderError();
}
if (DataRecord.IsExplicitlyClosed) {
throw EntityUtil.DataReaderClosed(methodName);
}
}
}
///
/// implementation for DbDataReader.Close() method
///
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();
}
}
}
///
/// implementation for DbDataReader.GetEnumerator() method
///
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
override public IEnumerator GetEnumerator() {
IEnumerator result = new DbEnumerator((IDataReader)this, true); // We always want to close the reader;
return result;
}
///
/// implementation for DbDataReader.GetSchemaTable() method
///
/// This is awaiting some common code
///
///
/// GetSchemaTable is not supported at this time
override public DataTable GetSchemaTable() {
throw EntityUtil.NotSupported(System.Data.Entity.Strings.ADP_GetSchemaTableIsNotSupported);
}
///
/// implementation for DbDataReader.NextResult() method
///
/// since the bridge currently doesn't support multiple results in a
/// single command, this always returns false.
///
///
override public bool NextResult() {
AssertReaderIsOpen("NextResult");
// SQLBUDT #631726 - ensure we close the records that may be
// outstanding...
CloseImplicitly();
// Consume results in the source collection to ensure that the
// store reader and the bridge data reader are in the same state.
// If we are not a root reader, we do not 'own' the store reader
// and do nothing.
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();
}
// Reset any state on our attached data record, since we've now
// gone past the end of the reader.
DataRecord.SetRecordSource(null, false);
// NOTE: if the bridge ever supports multiple results in a single
// command, we'll need to change this, but for now we can't
// ever have another result.
return false;
}
///
/// implementation for DbDataReader.Read() method
///
///
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;
}
///
/// 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.
///
///
///
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
///
/// implementation for DbDataReader.DataRecordInfo property
///
public DataRecordInfo DataRecordInfo {
get {
AssertReaderIsOpen("DataRecordInfo");
DataRecordInfo result;
if (DataRecord.HasData) {
result = DataRecord.DataRecordInfo;
}
else {
result = DefaultRecordState.DataRecordInfo;
}
return result;
}
}
///
/// implementation for DbDataReader.FieldCount property
///
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;
}
}
///
/// implementation for DbDataReader.GetDataTypeName() method
///
///
///
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;
}
///
/// implementation for DbDataReader.GetFieldType() method
///
///
///
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;
}
///
/// implementation for DbDataReader.GetName() method
///
///
///
override public string GetName(int ordinal) {
AssertReaderIsOpen("GetName");
string result;
if (DataRecord.HasData) {
result = DataRecord.GetName(ordinal);
}
else {
result = DefaultRecordState.GetName(ordinal);
}
return result;
}
///
/// implementation for DbDataReader.GetOrdinal() method
///
///
///
override public int GetOrdinal(string name) {
AssertReaderIsOpen("GetOrdinal");
int result;
if (DataRecord.HasData) {
result = DataRecord.GetOrdinal(name);
}
else {
result = DefaultRecordState.GetOrdinal(name);
}
return result;
}
///
/// implementation for DbDataReader.GetProviderSpecificFieldType() method
///
///
///
/// GetProviderSpecificFieldType is not supported at this time
[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
///
/// implementation for DbDataReader[ordinal] indexer value getter
///
override public object this[int ordinal] {
get {
return DataRecord[ordinal];
}
}
///
/// implementation for DbDataReader[name] indexer value getter
///
override public object this[string name] {
get {
int ordinal = GetOrdinal(name);
return DataRecord[ordinal];
}
}
///
/// implementation for DbDataReader.GetProviderSpecificValue() method
///
///
///
/// GetProviderSpecificValue is not supported at this time
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public override object GetProviderSpecificValue(int ordinal) {
throw EntityUtil.NotSupported();
}
///
/// implementation for DbDataReader.GetProviderSpecificValues() method
///
///
///
/// GetProviderSpecificValues is not supported at this time
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public override int GetProviderSpecificValues(object[] values) {
throw EntityUtil.NotSupported();
}
///
/// implementation for DbDataReader.GetValue() method
///
///
///
override public Object GetValue(int ordinal) {
return DataRecord.GetValue(ordinal);
}
///
/// implementation for DbDataReader.GetValues() method
///
///
///
override public int GetValues(object[] values) {
return DataRecord.GetValues(values);
}
#endregion
#region simple scalar value getter methods
///
/// implementation for DbDataReader.GetBoolean() method
///
///
///
override public bool GetBoolean(int ordinal) {
return DataRecord.GetBoolean(ordinal);
}
///
/// implementation for DbDataReader.GetByte() method
///
///
///
override public byte GetByte(int ordinal) {
return DataRecord.GetByte(ordinal);
}
///
/// implementation for DbDataReader.GetChar() method
///
///
///
override public char GetChar(int ordinal) {
return DataRecord.GetChar(ordinal);
}
///
/// implementation for DbDataReader.GetDateTime() method
///
///
///
override public DateTime GetDateTime(int ordinal) {
return DataRecord.GetDateTime(ordinal);
}
///
/// implementation for DbDataReader.GetDecimal() method
///
///
///
override public Decimal GetDecimal(int ordinal) {
return DataRecord.GetDecimal(ordinal);
}
///
/// implementation for DbDataReader.GetDouble() method
///
///
///
override public double GetDouble(int ordinal) {
return DataRecord.GetDouble(ordinal);
}
///
/// implementation for DbDataReader.GetFloat() method
///
///
///
override public float GetFloat(int ordinal) {
return DataRecord.GetFloat(ordinal);
}
///
/// implementation for DbDataReader.GetGuid() method
///
///
///
override public Guid GetGuid(int ordinal) {
return DataRecord.GetGuid(ordinal);
}
///
/// implementation for DbDataReader.GetInt16() method
///
///
///
override public Int16 GetInt16(int ordinal) {
return DataRecord.GetInt16(ordinal);
}
///
/// implementation for DbDataReader.GetInt32() method
///
///
///
override public Int32 GetInt32(int ordinal) {
return DataRecord.GetInt32(ordinal);
}
///
/// implementation for DbDataReader.GetInt64() method
///
///
///
override public Int64 GetInt64(int ordinal) {
return DataRecord.GetInt64(ordinal);
}
///
/// implementation for DbDataReader.GetString() method
///
///
///
override public String GetString(int ordinal) {
return DataRecord.GetString(ordinal);
}
///
/// implementation for DbDataReader.IsDBNull() method
///
///
///
override public bool IsDBNull(int ordinal) {
return DataRecord.IsDBNull(ordinal);
}
#endregion
#region chunking scalar value getter methods
///
/// implementation for DbDataReader.GetBytes() method
///
///
///
///
///
///
///
override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) {
return DataRecord.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
}
///
/// implementation for DbDataReader.GetChars() method
///
///
///
///
///
///
///
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
///
/// implementation for DbDataReader.GetData() method
///
///
///
override protected DbDataReader GetDbDataReader(int ordinal) {
return (DbDataReader)DataRecord.GetData(ordinal);
}
///
/// implementation for DbDataReader.GetDataRecord() method
///
///
///
public DbDataRecord GetDataRecord(int ordinal) {
return DataRecord.GetDataRecord(ordinal);
}
///
/// Used to return a nested result
///
///
///
public DbDataReader GetDataReader(int ordinal) {
return this.GetDbDataReader(ordinal);
}
#endregion
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MethodInfo.cs
- OutputScopeManager.cs
- WorkflowApplicationException.cs
- MediaContext.cs
- TransformGroup.cs
- HostedTcpTransportManager.cs
- ETagAttribute.cs
- UnsafeNativeMethodsTablet.cs
- ResourceDescriptionAttribute.cs
- ColumnMapCopier.cs
- ServiceOperation.cs
- TaskDesigner.cs
- PermissionRequestEvidence.cs
- ConfigurationException.cs
- Parser.cs
- AQNBuilder.cs
- TextBox.cs
- ImageFormat.cs
- Viewport3DVisual.cs
- CurrentChangingEventManager.cs
- OneToOneMappingSerializer.cs
- EvidenceBase.cs
- WebPartsSection.cs
- WindowsAuthenticationEventArgs.cs
- Merger.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- ImagingCache.cs
- DataGridCaption.cs
- ChangePasswordAutoFormat.cs
- XmlNodeComparer.cs
- SecureEnvironment.cs
- DateTimeFormatInfo.cs
- RawStylusInputCustomData.cs
- ManagedFilter.cs
- TableItemStyle.cs
- Invariant.cs
- ColorInterpolationModeValidation.cs
- TextEditorTyping.cs
- NetworkInformationException.cs
- AddInIpcChannel.cs
- SharedUtils.cs
- StaticTextPointer.cs
- WindowsHyperlink.cs
- OuterGlowBitmapEffect.cs
- TextPointerBase.cs
- SafeThreadHandle.cs
- FunctionNode.cs
- TraceListener.cs
- AvTrace.cs
- XmlElementList.cs
- DbConnectionStringBuilder.cs
- UnderstoodHeaders.cs
- PropertyIDSet.cs
- SharedUtils.cs
- UrlMappingsModule.cs
- PackWebRequest.cs
- UrlAuthorizationModule.cs
- SByte.cs
- InternalConfigSettingsFactory.cs
- Query.cs
- ExpressionLexer.cs
- MailMessage.cs
- InteropExecutor.cs
- PropertyTabChangedEvent.cs
- ADConnectionHelper.cs
- MergeLocalizationDirectives.cs
- WebReferencesBuildProvider.cs
- ToolStripDropDownClosingEventArgs.cs
- AutomationPatternInfo.cs
- RemoveStoryboard.cs
- XmlAttributeAttribute.cs
- WebConvert.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- Point4DValueSerializer.cs
- SiteMapNode.cs
- DbConnectionPoolIdentity.cs
- SetterBase.cs
- WebConvert.cs
- HandlerBase.cs
- XmlSiteMapProvider.cs
- DisplayMemberTemplateSelector.cs
- EntityUtil.cs
- WebPartDescriptionCollection.cs
- Char.cs
- ReferencedType.cs
- UnionCqlBlock.cs
- XmlException.cs
- XdrBuilder.cs
- EdmComplexPropertyAttribute.cs
- Win32MouseDevice.cs
- sqlmetadatafactory.cs
- ZipIOLocalFileBlock.cs
- HtmlElementEventArgs.cs
- CriticalHandle.cs
- MTConfigUtil.cs
- DataException.cs
- JavaScriptSerializer.cs
- RectAnimationClockResource.cs
- NavigationWindowAutomationPeer.cs
- VisualBasicSettings.cs