/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / DataRecord.cs / 1305376 / DataRecord.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
namespace System.Data.Objects
{
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Diagnostics;
using System.ComponentModel;
///
/// Instances of this class would be returned to user via Query<T>
///
internal sealed class MaterializedDataRecord : DbDataRecord, IExtendedDataRecord, ICustomTypeDescriptor
{
private FieldNameLookup _fieldNameLookup;
private DataRecordInfo _recordInfo;
private readonly MetadataWorkspace _workspace;
private readonly TypeUsage _edmUsage;
private readonly object[] _values;
///
///
///
internal MaterializedDataRecord(MetadataWorkspace workspace, TypeUsage edmUsage, object[] values)
{
Debug.Assert(null != edmUsage && null != values, "null recordType or values");
_workspace = workspace;
_edmUsage = edmUsage;
#if DEBUG
for (int i = 0; i < values.Length; ++i)
{
Debug.Assert(null != values[i], "should have been DBNull.Value");
}
#endif
_values = values; // take ownership of the array
}
///
///
///
public DataRecordInfo DataRecordInfo
{
get
{
if (null == _recordInfo)
{ // delay creation of DataRecordInfo until necessary
if (null == _workspace)
{
// When _workspace is null, we are materializing PODR.
// In this case, emdUsage describes a RowType.
Debug.Assert(Helper.IsRowType(_edmUsage.EdmType), "Edm type should be Row Type");
_recordInfo = new DataRecordInfo(_edmUsage);
}
else
{
_recordInfo = new DataRecordInfo(_workspace.GetOSpaceTypeUsage(_edmUsage));
}
Debug.Assert(_values.Length == _recordInfo.FieldMetadata.Count, "wrong values array size");
}
return _recordInfo;
}
}
///
///
///
public override int FieldCount
{
get
{
return _values.Length;
}
}
///
///
///
public override object this[int ordinal]
{
get
{
return GetValue(ordinal);
}
}
///
///
///
public override object this[string name]
{
get
{
return GetValue(GetOrdinal(name));
}
}
///
///
///
public override bool GetBoolean(int ordinal)
{
return ((bool)_values[ordinal]);
}
///
///
///
public override byte GetByte(int ordinal)
{
return ((byte)_values[ordinal]);
}
///
///
///
public override long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)
{
int cbytes = 0;
int ndataIndex;
byte[] data = (byte[])_values[ordinal];
cbytes = data.Length;
// since arrays can't handle 64 bit values and this interface doesn't
// allow chunked access to data, a dataIndex outside the rang of Int32
// is invalid
if (fieldOffset > Int32.MaxValue)
{
throw EntityUtil.InvalidSourceBufferIndex(cbytes, fieldOffset, "fieldOffset");
}
ndataIndex = (int)fieldOffset;
// if no buffer is passed in, return the number of characters we have
if (null == buffer)
return cbytes;
try
{
if (ndataIndex < cbytes)
{
// help the user out in the case where there's less data than requested
if ((ndataIndex + length) > cbytes)
cbytes = cbytes - ndataIndex;
else
cbytes = length;
}
Array.Copy(data, ndataIndex, buffer, bufferOffset, cbytes);
}
catch (Exception e)
{
//
if (EntityUtil.IsCatchableExceptionType(e))
{
cbytes = data.Length;
if (length < 0)
throw EntityUtil.InvalidDataLength(length);
// if bad buffer index, throw
if (bufferOffset < 0 || bufferOffset >= buffer.Length)
throw EntityUtil.InvalidDestinationBufferIndex(length, bufferOffset, "bufferOffset");
// if bad data index, throw
if (fieldOffset < 0 || fieldOffset >= cbytes)
throw EntityUtil.InvalidSourceBufferIndex(length, fieldOffset, "fieldOffset");
// if there is not enough room in the buffer for data
if (cbytes + bufferOffset > buffer.Length)
throw EntityUtil.InvalidBufferSizeOrIndex(cbytes, bufferOffset);
}
throw;
}
return cbytes;
}
///
///
///
public override char GetChar(int ordinal)
{
return ((string)GetValue(ordinal))[0];
}
///
///
///
public override long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)
{
int cchars = 0;
int ndataIndex;
string data = (string)_values[ordinal];
cchars = data.Length;
// since arrays can't handle 64 bit values and this interface doesn't
// allow chunked access to data, a dataIndex outside the rang of Int32
// is invalid
if (fieldOffset > Int32.MaxValue)
{
throw EntityUtil.InvalidSourceBufferIndex(cchars, fieldOffset, "fieldOffset");
}
ndataIndex = (int)fieldOffset;
// if no buffer is passed in, return the number of characters we have
if (null == buffer)
return cchars;
try
{
if (ndataIndex < cchars)
{
// help the user out in the case where there's less data than requested
if ((ndataIndex + length) > cchars)
cchars = cchars - ndataIndex;
else
cchars = length;
}
data.CopyTo(ndataIndex, buffer, bufferOffset, cchars);
}
catch (Exception e)
{
//
if (EntityUtil.IsCatchableExceptionType(e))
{
cchars = data.Length;
if (length < 0)
throw EntityUtil.InvalidDataLength(length);
// if bad buffer index, throw
if (bufferOffset < 0 || bufferOffset >= buffer.Length)
throw EntityUtil.InvalidDestinationBufferIndex(buffer.Length, bufferOffset, "bufferOffset");
// if bad data index, throw
if (fieldOffset < 0 || fieldOffset >= cchars)
throw EntityUtil.InvalidSourceBufferIndex(cchars, fieldOffset, "fieldOffset");
// if there is not enough room in the buffer for data
if (cchars + bufferOffset > buffer.Length)
throw EntityUtil.InvalidBufferSizeOrIndex(cchars, bufferOffset);
}
throw;
}
return cchars;
}
///
///
///
public DbDataRecord GetDataRecord(int ordinal)
{
return ((DbDataRecord)_values[ordinal]);
}
///
/// Used to return a nested result
///
public DbDataReader GetDataReader(int i)
{
return this.GetDbDataReader(i);
}
///
///
///
public override string GetDataTypeName(int ordinal)
{
return GetMember(ordinal).TypeUsage.EdmType.Name;
}
///
///
///
public override DateTime GetDateTime(int ordinal)
{
return ((DateTime)_values[ordinal]);
}
///
///
///
public override Decimal GetDecimal(int ordinal)
{
return ((Decimal)_values[ordinal]);
}
///
///
///
public override double GetDouble(int ordinal)
{
return ((double)_values[ordinal]);
}
///
///
///
public override Type GetFieldType(int ordinal)
{
EdmType edmMemberType = GetMember(ordinal).TypeUsage.EdmType;
if (Helper.IsPrimitiveType(edmMemberType))
{
return ((PrimitiveType)edmMemberType).ClrEquivalentType;
}
return typeof(System.Object);
}
///
///
///
public override float GetFloat(int ordinal)
{
return ((float)_values[ordinal]);
}
///
///
///
public override Guid GetGuid(int ordinal)
{
return ((Guid)_values[ordinal]);
}
///
///
///
public override Int16 GetInt16(int ordinal)
{
return ((Int16)_values[ordinal]);
}
///
///
///
public override Int32 GetInt32(int ordinal)
{
return ((Int32)_values[ordinal]);
}
///
///
///
public override Int64 GetInt64(int ordinal)
{
return ((Int64)_values[ordinal]);
}
///
///
///
public override string GetName(int ordinal)
{
return GetMember(ordinal).Name;
}
///
///
///
public override int GetOrdinal(string name)
{
if (null == _fieldNameLookup)
{
_fieldNameLookup = new FieldNameLookup(this, -1);
}
return _fieldNameLookup.GetOrdinal(name);
}
///
///
///
public override string GetString(int ordinal)
{
return ((string)_values[ordinal]);
}
///
///
///
public override object GetValue(int ordinal)
{
return _values[ordinal];
}
///
///
///
public override int GetValues(object[] values)
{
if (null == values)
{
throw EntityUtil.ArgumentNull("values");
}
int copyLen = Math.Min(values.Length, FieldCount);
for (int i = 0; i < copyLen; ++i)
{
values[i] = _values[i];
}
return copyLen;
}
private EdmMember GetMember(int ordinal)
{
return DataRecordInfo.FieldMetadata[ordinal].FieldType;
}
///
///
///
public override bool IsDBNull(int ordinal)
{
return (DBNull.Value == _values[ordinal]);
}
#region ICustomTypeDescriptor implementation
//[[....]] Reference: http://msdn.microsoft.com/msdnmag/issues/05/04/NETMatters/
//Holds all of the PropertyDescriptors for the PrimitiveType objects in _values
private PropertyDescriptorCollection _propertyDescriptors = null;
private FilterCache _filterCache;
//Stores an AttributeCollection for each PrimitiveType object in _values
Dictionary