Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / ResultAssembly / BridgeDataRecord.cs / 1305376 / BridgeDataRecord.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- 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.PlanCompiler; using System.Diagnostics; using System.Text; using System.Threading; ////// DbDataRecord functionality for the bridge. /// sealed internal class BridgeDataRecord : DbDataRecord, IExtendedDataRecord { #region state ////// How deep down the hierarchy are we? /// internal readonly int Depth; ////// Where the data comes from /// private readonly ShaperShaper; /// /// The current record that we're responsible for; this will change from row to row /// on the source data reader. Will be set to null when parent the enumerator has /// returned false. /// private RecordState _source; ////// Current state of the record; /// private Status _status; private enum Status { Open = 0, ClosedImplicitly = 1, ClosedExplicitly = 2, }; ////// the column ordinal of the last column read, used to enforce sequential access /// private int _lastColumnRead; ////// the last data offset of a chunking read returned, used to enforce sequential access /// private long _lastDataOffsetRead; ////// the last ordinal that IsDBNull was called for; used to avoid re-reading the value; /// private int _lastOrdinalCheckedForNull; ////// value, of the last column that IsDBNull was called for; used to avoid re-reading the value; /// private object _lastValueCheckedForNull; ////// Set to the current data record when we hand them out. (For data reader columns, /// we use it's attached data record) The Close, GetValue and Read methods ensures /// that this is implicitly closed when we move past it. /// private BridgeDataReader _currentNestedReader; private BridgeDataRecord _currentNestedRecord; #endregion #region constructors internal BridgeDataRecord(Shapershaper, int depth) : base() { Debug.Assert(null != shaper, "null shaper?"); Shaper = shaper; Depth = depth; // Rest of state is set through the SetRecordSource method. } #endregion #region state management /// /// Called by our owning datareader when it is explicitly closed; will /// not be called for nested structures, they go through the ClosedImplicitly. /// path instead. /// internal void CloseExplicitly() { _status = Status.ClosedExplicitly; _source = null; // can't have data any longer once we're closed. CloseNestedObjectImplicitly(); } ////// Called by our parent object to ensure that we're marked as implicitly /// closed; will not be called for root level data readers. /// internal void CloseImplicitly() { _status = Status.ClosedImplicitly; _source = null; // can't have data any longer once we're closed. CloseNestedObjectImplicitly(); } ////// Ensure that whatever column we're currently processing is implicitly closed; /// private void CloseNestedObjectImplicitly() { // it would be nice to use Interlocked.Exchange to avoid multi-thread `race condition risk // when the the bridge is being misused by the user accessing it with multiple threads. // but this is called frequently enough to have a performance impact BridgeDataRecord currentNestedRecord = _currentNestedRecord; if (null != currentNestedRecord) { _currentNestedRecord = null; currentNestedRecord.CloseImplicitly(); } BridgeDataReader currentNestedReader = _currentNestedReader; if (null != currentNestedReader) { _currentNestedReader = null; currentNestedReader.CloseImplicitly(); } } ////// Should be called after each Read on the data reader. /// internal void SetRecordSource(RecordState newSource, bool hasData) { Debug.Assert(null == _currentNestedRecord, "didn't close the nested record?"); Debug.Assert(null == _currentNestedReader, "didn't close the nested reader?"); // A peculiar behavior of IEnumerator is that when MoveNext() returns // false, the Current still points to the last value, which is not // what we really want to reflect here. if (hasData) { Debug.Assert(null != newSource, "hasData but null newSource?"); // this shouldn't happen... _source = newSource; } else { _source = null; } _status = Status.Open; _lastColumnRead = -1; _lastDataOffsetRead = -1; _lastOrdinalCheckedForNull = -1; _lastValueCheckedForNull = null; } #endregion #region assertion helpers ////// Ensures that the reader is actually open, and throws an exception if not /// private void AssertReaderIsOpen() { if (IsExplicitlyClosed) { throw EntityUtil.ClosedDataReaderError(); } if (IsImplicitlyClosed) { throw EntityUtil.ImplicitlyClosedDataReaderError(); } } ////// Helper method. /// private void AssertReaderIsOpenWithData() { AssertReaderIsOpen(); if (!HasData) { throw EntityUtil.NoData(); } } ////// Ensures that sequential access rules are being obeyed for non-chunking /// getter methods, throws the appropriate exception if not. Also ensures /// that the last column/chunk is set appropriately. /// /// private void AssertSequentialAccess(int ordinal) { Debug.Assert(null != _source, "null _source?"); // we should have already called AssertReaderIsOpen. if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } if (_lastColumnRead >= ordinal) { throw EntityUtil.NonSequentialColumnAccess(ordinal, _lastColumnRead + 1); } _lastColumnRead = ordinal; // SQLBUDT #442001 -- we need to mark things that are not using GetBytes/GetChars // in a way that prevents them from being read a second time // using those methods. Pointing past any potential data is // how we do that. _lastDataOffsetRead = long.MaxValue; } ////// Ensures that sequential access rules are being obeyed for chunking /// getter methods, throws the appropriate exception if not. Also ensures /// that the last column/chunk is set appropriately. /// /// /// /// private void AssertSequentialAccess(int ordinal, long dataOffset, string methodName) { Debug.Assert(null != _source, "null _source?"); // we should have already called AssertReaderIsOpen. if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } if (_lastColumnRead > ordinal || (_lastColumnRead == ordinal && _lastDataOffsetRead == long.MaxValue)) { throw EntityUtil.NonSequentialColumnAccess(ordinal, _lastColumnRead + 1); } if (_lastColumnRead == ordinal) { if (_lastDataOffsetRead >= dataOffset) { throw EntityUtil.NonSequentialChunkAccess(dataOffset, _lastDataOffsetRead + 1, methodName); } // _lastDataOffsetRead will be set by GetBytes/GetChars, since we need to set it // to the last offset that was actually read, which isn't necessarily what was // requested. } else { // Doin' a new thang... _lastColumnRead = ordinal; _lastDataOffsetRead = -1; } } ////// True when the record has data (SetRecordSource was called with true) /// internal bool HasData { get { bool result = (_source != null); return result; } } ////// True so long as we haven't been closed either implicity or explictly /// internal bool IsClosed { get { return (_status != Status.Open); } } ////// Determine whether we have been explicitly closed by our owning /// data reader; only data records that are responsible for processing /// data reader requests can be explicitly closed; /// internal bool IsExplicitlyClosed { get { return (_status == Status.ClosedExplicitly); } } ////// Determine whether the parent data reader or record moved on from /// where we can be considered open, (because the consumer of the /// parent data reader/record called either the GetValue() or Read() /// methods on the parent); /// internal bool IsImplicitlyClosed { get { return (_status == Status.ClosedImplicitly); } } #endregion #region metadata properties and methods ////// implementation of DbDataRecord.DataRecordInfo property /// public DataRecordInfo DataRecordInfo { get { AssertReaderIsOpen(); DataRecordInfo result = _source.DataRecordInfo; return result; } } ////// implementation of DbDataRecord.FieldCount property /// override public int FieldCount { get { AssertReaderIsOpen(); return _source.ColumnCount; } } ////// Helper method to get the edm TypeUsage for the specified column; /// /// If the column requested is a record, we'll pick up whatever the /// current record says it is, otherwise we'll take whatever was stored /// on our record state. /// /// ///private TypeUsage GetTypeUsage(int ordinal) { // Some folks are picky about the exception we throw if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } TypeUsage result; // RecordState recordState = _source.CurrentColumnValues[ordinal] as RecordState; if (null != recordState) { result = recordState.DataRecordInfo.RecordType; } else { result = _source.GetTypeUsage(ordinal); } return result; } /// /// implementation of DbDataRecord.GetDataTypeName() method /// /// ///override public string GetDataTypeName(int ordinal) { AssertReaderIsOpenWithData(); return TypeHelpers.GetFullName(GetTypeUsage(ordinal)); } /// /// implementation of DbDataRecord.GetFieldType() method /// /// ///override public Type GetFieldType(int ordinal) { AssertReaderIsOpenWithData(); return BridgeDataReader.GetClrTypeFromTypeMetadata(GetTypeUsage(ordinal)); } /// /// implementation of DbDataRecord.GetName() method /// /// ///override public string GetName(int ordinal) { AssertReaderIsOpen(); return _source.GetName(ordinal); } /// /// implementation of DbDataRecord.GetOrdinal() method /// /// ///override public int GetOrdinal(string name) { AssertReaderIsOpen(); return _source.GetOrdinal(name); } #endregion #region general getter methods and indexer properties /// /// implementation for DbDataRecord[ordinal] indexer property /// /// ///override public object this[int ordinal] { get { return GetValue(ordinal); } } /// /// implementation for DbDataRecord[name] indexer property /// /// ///override public object this[string name] { get { return GetValue(GetOrdinal(name)); } } /// /// implementation for DbDataRecord.GetValue() method /// /// This method is used by most of the column getters on this /// class to retrieve the value from the source reader. Therefore, /// it asserts all the good things, like that the reader is open, /// and that it has data, and that you're not trying to circumvent /// sequential access requirements. /// /// ///override public Object GetValue(int ordinal) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal); object result = null; if (ordinal == _lastOrdinalCheckedForNull) { result = _lastValueCheckedForNull; } else { _lastOrdinalCheckedForNull = -1; _lastValueCheckedForNull = null; CloseNestedObjectImplicitly(); result = _source.CurrentColumnValues[ordinal]; // If we've got something that's nested, then make sure we // update the current nested record with it so we can be certain // to close it implicitly when we move past it. if (_source.IsNestedObject(ordinal)) { result = GetNestedObjectValue(result); } } return result; } /// /// For nested objects (records/readers) we have a bit more work to do; this /// method extracts it all out from the main GetValue method so it doesn't /// have to be so big. /// /// ///private object GetNestedObjectValue(object result) { if (result != DBNull.Value) { RecordState recordState = result as RecordState; if (null != recordState) { if (recordState.IsNull) { result = DBNull.Value; } else { BridgeDataRecord nestedRecord = new BridgeDataRecord(Shaper, Depth + 1); nestedRecord.SetRecordSource(recordState, true); result = nestedRecord; _currentNestedRecord = nestedRecord; _currentNestedReader = null; } } else { Coordinator coordinator = result as Coordinator ; if (null != coordinator) { BridgeDataReader nestedReader = new BridgeDataReader(Shaper, coordinator.TypedCoordinatorFactory, Depth + 1); result = nestedReader; _currentNestedRecord = null; _currentNestedReader = nestedReader; } else { Debug.Fail("unexpected type of nested object result: " + result.GetType().ToString()); } } } return result; } /// /// implementation for DbDataRecord.GetValues() method /// /// ///override public int GetValues(object[] values) { EntityUtil.CheckArgumentNull(values, "values"); int copy = Math.Min(values.Length, FieldCount); for (int i = 0; i < copy; ++i) { values[i] = GetValue(i); } return copy; } #endregion #region simple scalar value getter methods /// /// implementation of DbDataRecord.GetBoolean() method /// /// ///override public bool GetBoolean(int ordinal) { return (bool)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetByte() method /// /// ///override public byte GetByte(int ordinal) { return (byte)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetChar() method /// /// ///override public char GetChar(int ordinal) { return (char)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDateTime() method /// /// ///override public DateTime GetDateTime(int ordinal) { return (DateTime)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDecimal() method /// /// ///override public Decimal GetDecimal(int ordinal) { return (Decimal)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDouble() method /// /// ///override public double GetDouble(int ordinal) { return (double)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetFloat() method /// /// ///override public float GetFloat(int ordinal) { return (float)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetGuid() method /// /// ///override public Guid GetGuid(int ordinal) { return (Guid)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt16() method /// /// ///override public Int16 GetInt16(int ordinal) { return (Int16)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt32() method /// /// ///override public Int32 GetInt32(int ordinal) { return (Int32)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt64() method /// /// ///override public Int64 GetInt64(int ordinal) { return (Int64)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetString() method /// /// ///override public String GetString(int ordinal) { return (String)GetValue(ordinal); } /// /// implementation of DbDataRecord.IsDBNull() method /// /// ///override public bool IsDBNull(int ordinal) { // This seems like a hack, but the the problem is that I need // to make sure I don't monkey with caching things, and if I // call IsDBNull directly on the store reader, I'll potentially // lose data because I'm expecting SequentialAccess rules. object columnValue = GetValue(ordinal); // Need to backup one because we technically didn't read the // value yet but the GetValue method advanced our pointer to // what the value was. Another hack, but it's way less code // than trying to avoid advancing to begin with. _lastColumnRead--; _lastDataOffsetRead = -1; // So as to avoid reconstructing nested records, readers, and // rereading data from the iterator source cache, we just cache // the value we read and the ordinal it came from, so if someone // is doing the right thing(TM) and calling IsDBNull before calling // GetValue, we won't construct another one. _lastValueCheckedForNull = columnValue; _lastOrdinalCheckedForNull = ordinal; bool result = (DBNull.Value == columnValue); return result; } #endregion #region chunking scalar value getter methods /// /// implementation for DbDataRecord.GetBytes() method /// /// /// /// /// /// ///override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal, dataOffset, "GetBytes"); long result = _source.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); if (buffer != null) { _lastDataOffsetRead = dataOffset + result - 1; // just what was read, nothing more. } return result; } /// /// implementation for DbDataRecord.GetChars() method /// /// /// /// /// /// ///override public long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal, dataOffset, "GetChars"); long result = _source.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); if (buffer != null) { _lastDataOffsetRead = dataOffset + result - 1; // just what was read, nothing more. } return result; } #endregion #region complex type getters /// /// implementation for DbDataRecord.GetData() method /// /// ///override protected DbDataReader GetDbDataReader(int ordinal) { return (DbDataReader)GetValue(ordinal); } /// /// implementation for DbDataRecord.GetDataRecord() method /// /// ///public DbDataRecord GetDataRecord(int ordinal) { return (DbDataRecord)GetValue(ordinal); } /// /// Used to return a nested result /// /// ///public DbDataReader GetDataReader(int ordinal) { return this.GetDbDataReader(ordinal); } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- 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.PlanCompiler; using System.Diagnostics; using System.Text; using System.Threading; ////// DbDataRecord functionality for the bridge. /// sealed internal class BridgeDataRecord : DbDataRecord, IExtendedDataRecord { #region state ////// How deep down the hierarchy are we? /// internal readonly int Depth; ////// Where the data comes from /// private readonly ShaperShaper; /// /// The current record that we're responsible for; this will change from row to row /// on the source data reader. Will be set to null when parent the enumerator has /// returned false. /// private RecordState _source; ////// Current state of the record; /// private Status _status; private enum Status { Open = 0, ClosedImplicitly = 1, ClosedExplicitly = 2, }; ////// the column ordinal of the last column read, used to enforce sequential access /// private int _lastColumnRead; ////// the last data offset of a chunking read returned, used to enforce sequential access /// private long _lastDataOffsetRead; ////// the last ordinal that IsDBNull was called for; used to avoid re-reading the value; /// private int _lastOrdinalCheckedForNull; ////// value, of the last column that IsDBNull was called for; used to avoid re-reading the value; /// private object _lastValueCheckedForNull; ////// Set to the current data record when we hand them out. (For data reader columns, /// we use it's attached data record) The Close, GetValue and Read methods ensures /// that this is implicitly closed when we move past it. /// private BridgeDataReader _currentNestedReader; private BridgeDataRecord _currentNestedRecord; #endregion #region constructors internal BridgeDataRecord(Shapershaper, int depth) : base() { Debug.Assert(null != shaper, "null shaper?"); Shaper = shaper; Depth = depth; // Rest of state is set through the SetRecordSource method. } #endregion #region state management /// /// Called by our owning datareader when it is explicitly closed; will /// not be called for nested structures, they go through the ClosedImplicitly. /// path instead. /// internal void CloseExplicitly() { _status = Status.ClosedExplicitly; _source = null; // can't have data any longer once we're closed. CloseNestedObjectImplicitly(); } ////// Called by our parent object to ensure that we're marked as implicitly /// closed; will not be called for root level data readers. /// internal void CloseImplicitly() { _status = Status.ClosedImplicitly; _source = null; // can't have data any longer once we're closed. CloseNestedObjectImplicitly(); } ////// Ensure that whatever column we're currently processing is implicitly closed; /// private void CloseNestedObjectImplicitly() { // it would be nice to use Interlocked.Exchange to avoid multi-thread `race condition risk // when the the bridge is being misused by the user accessing it with multiple threads. // but this is called frequently enough to have a performance impact BridgeDataRecord currentNestedRecord = _currentNestedRecord; if (null != currentNestedRecord) { _currentNestedRecord = null; currentNestedRecord.CloseImplicitly(); } BridgeDataReader currentNestedReader = _currentNestedReader; if (null != currentNestedReader) { _currentNestedReader = null; currentNestedReader.CloseImplicitly(); } } ////// Should be called after each Read on the data reader. /// internal void SetRecordSource(RecordState newSource, bool hasData) { Debug.Assert(null == _currentNestedRecord, "didn't close the nested record?"); Debug.Assert(null == _currentNestedReader, "didn't close the nested reader?"); // A peculiar behavior of IEnumerator is that when MoveNext() returns // false, the Current still points to the last value, which is not // what we really want to reflect here. if (hasData) { Debug.Assert(null != newSource, "hasData but null newSource?"); // this shouldn't happen... _source = newSource; } else { _source = null; } _status = Status.Open; _lastColumnRead = -1; _lastDataOffsetRead = -1; _lastOrdinalCheckedForNull = -1; _lastValueCheckedForNull = null; } #endregion #region assertion helpers ////// Ensures that the reader is actually open, and throws an exception if not /// private void AssertReaderIsOpen() { if (IsExplicitlyClosed) { throw EntityUtil.ClosedDataReaderError(); } if (IsImplicitlyClosed) { throw EntityUtil.ImplicitlyClosedDataReaderError(); } } ////// Helper method. /// private void AssertReaderIsOpenWithData() { AssertReaderIsOpen(); if (!HasData) { throw EntityUtil.NoData(); } } ////// Ensures that sequential access rules are being obeyed for non-chunking /// getter methods, throws the appropriate exception if not. Also ensures /// that the last column/chunk is set appropriately. /// /// private void AssertSequentialAccess(int ordinal) { Debug.Assert(null != _source, "null _source?"); // we should have already called AssertReaderIsOpen. if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } if (_lastColumnRead >= ordinal) { throw EntityUtil.NonSequentialColumnAccess(ordinal, _lastColumnRead + 1); } _lastColumnRead = ordinal; // SQLBUDT #442001 -- we need to mark things that are not using GetBytes/GetChars // in a way that prevents them from being read a second time // using those methods. Pointing past any potential data is // how we do that. _lastDataOffsetRead = long.MaxValue; } ////// Ensures that sequential access rules are being obeyed for chunking /// getter methods, throws the appropriate exception if not. Also ensures /// that the last column/chunk is set appropriately. /// /// /// /// private void AssertSequentialAccess(int ordinal, long dataOffset, string methodName) { Debug.Assert(null != _source, "null _source?"); // we should have already called AssertReaderIsOpen. if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } if (_lastColumnRead > ordinal || (_lastColumnRead == ordinal && _lastDataOffsetRead == long.MaxValue)) { throw EntityUtil.NonSequentialColumnAccess(ordinal, _lastColumnRead + 1); } if (_lastColumnRead == ordinal) { if (_lastDataOffsetRead >= dataOffset) { throw EntityUtil.NonSequentialChunkAccess(dataOffset, _lastDataOffsetRead + 1, methodName); } // _lastDataOffsetRead will be set by GetBytes/GetChars, since we need to set it // to the last offset that was actually read, which isn't necessarily what was // requested. } else { // Doin' a new thang... _lastColumnRead = ordinal; _lastDataOffsetRead = -1; } } ////// True when the record has data (SetRecordSource was called with true) /// internal bool HasData { get { bool result = (_source != null); return result; } } ////// True so long as we haven't been closed either implicity or explictly /// internal bool IsClosed { get { return (_status != Status.Open); } } ////// Determine whether we have been explicitly closed by our owning /// data reader; only data records that are responsible for processing /// data reader requests can be explicitly closed; /// internal bool IsExplicitlyClosed { get { return (_status == Status.ClosedExplicitly); } } ////// Determine whether the parent data reader or record moved on from /// where we can be considered open, (because the consumer of the /// parent data reader/record called either the GetValue() or Read() /// methods on the parent); /// internal bool IsImplicitlyClosed { get { return (_status == Status.ClosedImplicitly); } } #endregion #region metadata properties and methods ////// implementation of DbDataRecord.DataRecordInfo property /// public DataRecordInfo DataRecordInfo { get { AssertReaderIsOpen(); DataRecordInfo result = _source.DataRecordInfo; return result; } } ////// implementation of DbDataRecord.FieldCount property /// override public int FieldCount { get { AssertReaderIsOpen(); return _source.ColumnCount; } } ////// Helper method to get the edm TypeUsage for the specified column; /// /// If the column requested is a record, we'll pick up whatever the /// current record says it is, otherwise we'll take whatever was stored /// on our record state. /// /// ///private TypeUsage GetTypeUsage(int ordinal) { // Some folks are picky about the exception we throw if (ordinal < 0 || ordinal >= _source.ColumnCount) { throw EntityUtil.ArgumentOutOfRange("ordinal"); } TypeUsage result; // RecordState recordState = _source.CurrentColumnValues[ordinal] as RecordState; if (null != recordState) { result = recordState.DataRecordInfo.RecordType; } else { result = _source.GetTypeUsage(ordinal); } return result; } /// /// implementation of DbDataRecord.GetDataTypeName() method /// /// ///override public string GetDataTypeName(int ordinal) { AssertReaderIsOpenWithData(); return TypeHelpers.GetFullName(GetTypeUsage(ordinal)); } /// /// implementation of DbDataRecord.GetFieldType() method /// /// ///override public Type GetFieldType(int ordinal) { AssertReaderIsOpenWithData(); return BridgeDataReader.GetClrTypeFromTypeMetadata(GetTypeUsage(ordinal)); } /// /// implementation of DbDataRecord.GetName() method /// /// ///override public string GetName(int ordinal) { AssertReaderIsOpen(); return _source.GetName(ordinal); } /// /// implementation of DbDataRecord.GetOrdinal() method /// /// ///override public int GetOrdinal(string name) { AssertReaderIsOpen(); return _source.GetOrdinal(name); } #endregion #region general getter methods and indexer properties /// /// implementation for DbDataRecord[ordinal] indexer property /// /// ///override public object this[int ordinal] { get { return GetValue(ordinal); } } /// /// implementation for DbDataRecord[name] indexer property /// /// ///override public object this[string name] { get { return GetValue(GetOrdinal(name)); } } /// /// implementation for DbDataRecord.GetValue() method /// /// This method is used by most of the column getters on this /// class to retrieve the value from the source reader. Therefore, /// it asserts all the good things, like that the reader is open, /// and that it has data, and that you're not trying to circumvent /// sequential access requirements. /// /// ///override public Object GetValue(int ordinal) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal); object result = null; if (ordinal == _lastOrdinalCheckedForNull) { result = _lastValueCheckedForNull; } else { _lastOrdinalCheckedForNull = -1; _lastValueCheckedForNull = null; CloseNestedObjectImplicitly(); result = _source.CurrentColumnValues[ordinal]; // If we've got something that's nested, then make sure we // update the current nested record with it so we can be certain // to close it implicitly when we move past it. if (_source.IsNestedObject(ordinal)) { result = GetNestedObjectValue(result); } } return result; } /// /// For nested objects (records/readers) we have a bit more work to do; this /// method extracts it all out from the main GetValue method so it doesn't /// have to be so big. /// /// ///private object GetNestedObjectValue(object result) { if (result != DBNull.Value) { RecordState recordState = result as RecordState; if (null != recordState) { if (recordState.IsNull) { result = DBNull.Value; } else { BridgeDataRecord nestedRecord = new BridgeDataRecord(Shaper, Depth + 1); nestedRecord.SetRecordSource(recordState, true); result = nestedRecord; _currentNestedRecord = nestedRecord; _currentNestedReader = null; } } else { Coordinator coordinator = result as Coordinator ; if (null != coordinator) { BridgeDataReader nestedReader = new BridgeDataReader(Shaper, coordinator.TypedCoordinatorFactory, Depth + 1); result = nestedReader; _currentNestedRecord = null; _currentNestedReader = nestedReader; } else { Debug.Fail("unexpected type of nested object result: " + result.GetType().ToString()); } } } return result; } /// /// implementation for DbDataRecord.GetValues() method /// /// ///override public int GetValues(object[] values) { EntityUtil.CheckArgumentNull(values, "values"); int copy = Math.Min(values.Length, FieldCount); for (int i = 0; i < copy; ++i) { values[i] = GetValue(i); } return copy; } #endregion #region simple scalar value getter methods /// /// implementation of DbDataRecord.GetBoolean() method /// /// ///override public bool GetBoolean(int ordinal) { return (bool)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetByte() method /// /// ///override public byte GetByte(int ordinal) { return (byte)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetChar() method /// /// ///override public char GetChar(int ordinal) { return (char)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDateTime() method /// /// ///override public DateTime GetDateTime(int ordinal) { return (DateTime)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDecimal() method /// /// ///override public Decimal GetDecimal(int ordinal) { return (Decimal)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetDouble() method /// /// ///override public double GetDouble(int ordinal) { return (double)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetFloat() method /// /// ///override public float GetFloat(int ordinal) { return (float)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetGuid() method /// /// ///override public Guid GetGuid(int ordinal) { return (Guid)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt16() method /// /// ///override public Int16 GetInt16(int ordinal) { return (Int16)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt32() method /// /// ///override public Int32 GetInt32(int ordinal) { return (Int32)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetInt64() method /// /// ///override public Int64 GetInt64(int ordinal) { return (Int64)GetValue(ordinal); } /// /// implementation of DbDataRecord.GetString() method /// /// ///override public String GetString(int ordinal) { return (String)GetValue(ordinal); } /// /// implementation of DbDataRecord.IsDBNull() method /// /// ///override public bool IsDBNull(int ordinal) { // This seems like a hack, but the the problem is that I need // to make sure I don't monkey with caching things, and if I // call IsDBNull directly on the store reader, I'll potentially // lose data because I'm expecting SequentialAccess rules. object columnValue = GetValue(ordinal); // Need to backup one because we technically didn't read the // value yet but the GetValue method advanced our pointer to // what the value was. Another hack, but it's way less code // than trying to avoid advancing to begin with. _lastColumnRead--; _lastDataOffsetRead = -1; // So as to avoid reconstructing nested records, readers, and // rereading data from the iterator source cache, we just cache // the value we read and the ordinal it came from, so if someone // is doing the right thing(TM) and calling IsDBNull before calling // GetValue, we won't construct another one. _lastValueCheckedForNull = columnValue; _lastOrdinalCheckedForNull = ordinal; bool result = (DBNull.Value == columnValue); return result; } #endregion #region chunking scalar value getter methods /// /// implementation for DbDataRecord.GetBytes() method /// /// /// /// /// /// ///override public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal, dataOffset, "GetBytes"); long result = _source.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); if (buffer != null) { _lastDataOffsetRead = dataOffset + result - 1; // just what was read, nothing more. } return result; } /// /// implementation for DbDataRecord.GetChars() method /// /// /// /// /// /// ///override public long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) { AssertReaderIsOpenWithData(); AssertSequentialAccess(ordinal, dataOffset, "GetChars"); long result = _source.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); if (buffer != null) { _lastDataOffsetRead = dataOffset + result - 1; // just what was read, nothing more. } return result; } #endregion #region complex type getters /// /// implementation for DbDataRecord.GetData() method /// /// ///override protected DbDataReader GetDbDataReader(int ordinal) { return (DbDataReader)GetValue(ordinal); } /// /// implementation for DbDataRecord.GetDataRecord() method /// /// ///public DbDataRecord GetDataRecord(int ordinal) { return (DbDataRecord)GetValue(ordinal); } /// /// Used to return a nested result /// /// ///public DbDataReader GetDataReader(int ordinal) { return this.GetDbDataReader(ordinal); } #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
- MobileUserControlDesigner.cs
- PageSettings.cs
- HelloMessageApril2005.cs
- PackWebResponse.cs
- IssuedTokenParametersElement.cs
- HtmlInputRadioButton.cs
- ThaiBuddhistCalendar.cs
- Int32RectConverter.cs
- TableTextElementCollectionInternal.cs
- TimeSpanOrInfiniteConverter.cs
- ManagementPath.cs
- EntityDataSourceChangedEventArgs.cs
- ResXDataNode.cs
- Select.cs
- SqlResolver.cs
- OracleCommandSet.cs
- PeerCollaboration.cs
- OdbcEnvironment.cs
- MetabaseServerConfig.cs
- SBCSCodePageEncoding.cs
- LineBreak.cs
- ScriptResourceHandler.cs
- XmlArrayItemAttributes.cs
- DataExchangeServiceBinder.cs
- TextEditorDragDrop.cs
- ControlIdConverter.cs
- HyperLink.cs
- UserControlAutomationPeer.cs
- SingleAnimation.cs
- HttpProfileGroupBase.cs
- HttpHandlersSection.cs
- Tag.cs
- ResourceWriter.cs
- ZipIOLocalFileDataDescriptor.cs
- XPathExpr.cs
- HMACSHA1.cs
- XmlFormatExtensionPrefixAttribute.cs
- SymLanguageType.cs
- FileStream.cs
- TabControlEvent.cs
- UnsafeNativeMethodsCLR.cs
- LinkedResourceCollection.cs
- OverrideMode.cs
- RangeBaseAutomationPeer.cs
- MeshGeometry3D.cs
- AvTraceFormat.cs
- MessageTraceRecord.cs
- BreakSafeBase.cs
- HtmlDocument.cs
- WithStatement.cs
- UserNameServiceElement.cs
- TimeStampChecker.cs
- mansign.cs
- RenderDataDrawingContext.cs
- TraceFilter.cs
- Region.cs
- CompiledScopeCriteria.cs
- TextProperties.cs
- EnvironmentPermission.cs
- Queue.cs
- SqlReferenceCollection.cs
- UserPersonalizationStateInfo.cs
- connectionpool.cs
- Utils.cs
- SqlConnectionPoolProviderInfo.cs
- TableItemPatternIdentifiers.cs
- FlowDocumentFormatter.cs
- SqlBuffer.cs
- ApplicationCommands.cs
- PropertyChangedEventArgs.cs
- DataGridViewCellValueEventArgs.cs
- UnsafeNativeMethods.cs
- KeyValueSerializer.cs
- TypeResolver.cs
- RegexRunnerFactory.cs
- MergeFailedEvent.cs
- TypeToken.cs
- TraceHwndHost.cs
- ScrollItemPattern.cs
- BoundField.cs
- ButtonPopupAdapter.cs
- EncodingNLS.cs
- Convert.cs
- SizeChangedEventArgs.cs
- DataFormats.cs
- SrgsDocumentParser.cs
- SafeNativeMethods.cs
- DocumentPageViewAutomationPeer.cs
- PeerObject.cs
- ByteViewer.cs
- MetadataItemSerializer.cs
- DesignTimeVisibleAttribute.cs
- RecordsAffectedEventArgs.cs
- WindowsPen.cs
- Form.cs
- DomNameTable.cs
- DomainLiteralReader.cs
- RegisteredDisposeScript.cs
- Oci.cs
- XhtmlBasicPhoneCallAdapter.cs