Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Data / System / Data / SqlClient / TdsValueSetter.cs / 4 / TdsValueSetter.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data.SqlClient { using Microsoft.SqlServer.Server; using System; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Data.SqlTypes; using System.Diagnostics; using System.Text; // TdsValueSetter handles writing a single value out to a TDS stream // This class can easily be extended to handle multiple versions of TDS by sub-classing and virtualizing // methods that have different formats or are not supported in one or the other version. internal class TdsValueSetter { #region Private fields private TdsParserStateObject _stateObj; // target to write to private SmiMetaData _metaData; // metadata describing value private bool _isPlp; // should this column be sent in PLP format? private bool _plpUnknownSent;// did we send initial UNKNOWN_LENGTH marker? private Encoder _encoder; // required for chunking character type data private SmiMetaData _variantType; // required for sql_variant #if DEBUG private int _currentOffset; // for chunking, verify that caller is using correct offsets #endif #endregion #region Exposed Construct/factory methods internal TdsValueSetter(TdsParserStateObject stateObj, SmiMetaData md) { _stateObj = stateObj; _metaData = md; _isPlp = MetaDataUtilsSmi.IsPlpFormat(md); _plpUnknownSent = false; _encoder = null; #if DEBUG _currentOffset = 0; #endif } #endregion #region Setters // Set value to null // valid for all types internal void SetDBNull() { Debug.Assert(!_plpUnknownSent, "Setting a column to null that we already stated sending!"); if (_isPlp) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_NULL, _stateObj); } else { switch(_metaData.SqlDbType) { case SqlDbType.BigInt: case SqlDbType.Bit: case SqlDbType.DateTime: case SqlDbType.Decimal: case SqlDbType.Float: case SqlDbType.Int: case SqlDbType.Money: case SqlDbType.Real: case SqlDbType.UniqueIdentifier: case SqlDbType.SmallDateTime: case SqlDbType.SmallInt: case SqlDbType.SmallMoney: case SqlDbType.TinyInt: case SqlDbType.Date: case SqlDbType.Time: case SqlDbType.DateTime2: case SqlDbType.DateTimeOffset: _stateObj.Parser.WriteByte(TdsEnums.FIXEDNULL, _stateObj); break; case SqlDbType.Binary: case SqlDbType.Char: case SqlDbType.Image: case SqlDbType.NChar: case SqlDbType.NText: case SqlDbType.NVarChar: case SqlDbType.Text: case SqlDbType.Timestamp: case SqlDbType.VarBinary: case SqlDbType.VarChar: _stateObj.Parser.WriteShort(TdsEnums.VARNULL, _stateObj); break; case SqlDbType.Udt: case SqlDbType.Xml: Debug.Assert(false, "PLP-only types shouldn't get to this point. Type: " + _metaData.SqlDbType); break; case SqlDbType.Variant: _stateObj.Parser.WriteInt(TdsEnums.FIXEDNULL, _stateObj); break; case SqlDbType.Structured: Debug.Assert(false, "Not yet implemented. Not needed until Structured UDTs"); break; default: Debug.Assert(false, "Unexpected SqlDbType: " + _metaData.SqlDbType); break; } } } // valid for SqlDbType.Bit internal void SetBoolean(Boolean value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBoolean)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(3, TdsEnums.SQLBIT, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } if (value) { _stateObj.Parser.WriteByte(1, _stateObj); } else { _stateObj.Parser.WriteByte(0, _stateObj); } } // valid for SqlDbType.TinyInt internal void SetByte(Byte value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetByte)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(3, TdsEnums.SQLINT1, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteByte(value, _stateObj); } // Semantics for SetBytes are to modify existing value, not overwrite // Use in combination with SetLength to ensure overwriting when necessary // valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml // (VarBinary assumed for variants) internal int SetBytes(long fieldOffset, byte[] buffer, int bufferOffset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBytes)); CheckSettingOffset(fieldOffset); SetBytesNoOffsetHandling(fieldOffset, buffer, bufferOffset, length); #if DEBUG _currentOffset += length; #endif return length; } private void SetBytesNoOffsetHandling(long fieldOffset, byte[] buffer, int bufferOffset, int length) { if (_isPlp) { if (!_plpUnknownSent) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, _stateObj); _plpUnknownSent = true; } // Write chunk length & chunk _stateObj.Parser.WriteInt(length, _stateObj); _stateObj.Parser.WriteByteArray(buffer, length, bufferOffset, _stateObj); } else { // Non-plp data must be sent in one chunk for now. #if DEBUG Debug.Assert(0 == _currentOffset, "SetBytes doesn't yet support chunking for non-plp data: " + _currentOffset); #endif Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4 + length, TdsEnums.SQLBIGVARBINARY, 2, _stateObj); } _stateObj.Parser.WriteShort(length, _stateObj); _stateObj.Parser.WriteByteArray(buffer, length, bufferOffset, _stateObj); } } internal void SetBytesLength(long length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBytes)); CheckSettingOffset(length); if (0 == length) { if (_isPlp) { Debug.Assert(!_plpUnknownSent, "A plpUnknown has already been sent before setting length to zero."); _stateObj.Parser.WriteLong(0, _stateObj); _plpUnknownSent = true; } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4, TdsEnums.SQLBIGVARBINARY, 2, _stateObj); } _stateObj.Parser.WriteShort(0, _stateObj); } } if (_plpUnknownSent) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); _plpUnknownSent = false; } #if DEBUG // _currentOffset = 0; #endif } // Semantics for SetChars are to modify existing value, not overwrite // Use in combination with SetLength to ensure overwriting when necessary // valid for character types: Char, VarChar, Text, NChar, NVarChar, NText // (NVarChar and global clr collation assumed for variants) internal int SetChars(long fieldOffset, char[] buffer, int bufferOffset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetChars)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { if (null == _encoder) { _encoder = _stateObj.Parser._defaultEncoding.GetEncoder(); } byte[] bytes = new byte[_encoder.GetByteCount(buffer, bufferOffset, length, false)]; _encoder.GetBytes(buffer, bufferOffset, length, bytes, 0, false); SetBytesNoOffsetHandling(fieldOffset, bytes, 0, bytes.Length); } else { CheckSettingOffset(fieldOffset); // Send via PLP format if we can. if (_isPlp) { // Handle initial PLP markers if (!_plpUnknownSent) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, _stateObj); _plpUnknownSent = true; } // Write chunk length _stateObj.Parser.WriteInt(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } else { // Non-plp data must be sent in one chunk for now. #if DEBUG Debug.Assert(0 == _currentOffset, "SetChars doesn't yet support chunking for non-plp data: " + _currentOffset); #endif if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantValue(new String(buffer, bufferOffset, length), length, 0, _stateObj); } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); _stateObj.Parser.WriteShort(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } } } #if DEBUG _currentOffset += length; #endif return length; } internal void SetCharsLength(long length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetChars)); CheckSettingOffset(length); if (0 == length) { if (_isPlp) { Debug.Assert(!_plpUnknownSent, "A plpUnknown has already been sent before setting length to zero."); _stateObj.Parser.WriteLong(0, _stateObj); _plpUnknownSent = true; } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); _stateObj.Parser.WriteShort(0, _stateObj); } } if (_plpUnknownSent) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); _plpUnknownSent = false; } _encoder = null; #if DEBUG // _currentOffset = 0; #endif } // valid for character types: Char, VarChar, Text, NChar, NVarChar, NText internal void SetString(string value, int offset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetString)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { char[] chars = value.ToCharArray(offset, length); bytes = _stateObj.Parser._defaultEncoding.GetBytes(chars); } SetBytes(0, bytes, 0, bytes.Length); SetBytesLength(bytes.Length); } else if (SqlDbType.Variant == _metaData.SqlDbType) { Debug.Assert(null != _variantType && SqlDbType.NVarChar == _variantType.SqlDbType, "Invalid variant type"); SqlCollation collation = new SqlCollation(); collation.LCID = checked((int)_variantType.LocaleId); collation.SqlCompareOptions = _variantType.CompareOptions; if (length * ADP.CharSize > TdsEnums.TYPE_SIZE_LIMIT) { // send as varchar for length greater than 4000 byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value.ToCharArray(offset, length)); } _stateObj.Parser.WriteSqlVariantHeader(9 + bytes.Length, TdsEnums.SQLBIGVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.Parser.WriteByte(collation.sortId, _stateObj); // propbytes: collation.SortId _stateObj.Parser.WriteShort(bytes.Length, _stateObj); // propbyte: varlen _stateObj.Parser.WriteByteArray(bytes, bytes.Length, 0, _stateObj); } else { _stateObj.Parser.WriteSqlVariantHeader(9 + length * ADP.CharSize, TdsEnums.SQLNVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.Parser.WriteByte(collation.sortId, _stateObj); // propbytes: collation.SortId _stateObj.Parser.WriteShort(length * ADP.CharSize, _stateObj); // propbyte: varlen _stateObj.Parser.WriteString(value, length, offset, _stateObj); } _variantType = null; } else if (_isPlp) { // Send the string as a complete PLP chunk. _stateObj.Parser.WriteLong(length*ADP.CharSize, _stateObj); // PLP total length _stateObj.Parser.WriteInt(length*ADP.CharSize, _stateObj); // Chunk length _stateObj.Parser.WriteString(value, length, offset, _stateObj); // Data if (length != 0) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); // Terminator } } else { _stateObj.Parser.WriteShort(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteString(value, length, offset, _stateObj); } } // valid for SqlDbType.SmallInt internal void SetInt16(Int16 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt16)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4, TdsEnums.SQLINT2, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteShort(value, _stateObj); } // valid for SqlDbType.Int internal void SetInt32(Int32 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt32)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(6, TdsEnums.SQLINT4, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteInt(value, _stateObj); } // valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney internal void SetInt64(Int64 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt64)); if (SqlDbType.Variant == _metaData.SqlDbType) { if (null == _variantType) { _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLINT8, 0, _stateObj); _stateObj.Parser.WriteLong(value, _stateObj); } else { Debug.Assert(SqlDbType.Money == _variantType.SqlDbType, "Invalid variant type"); _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLMONEY, 0, _stateObj); _stateObj.Parser.WriteInt((int)(value >> 0x20), _stateObj); _stateObj.Parser.WriteInt((int)value, _stateObj); _variantType = null; } } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); if (SqlDbType.SmallMoney == _metaData.SqlDbType) { _stateObj.Parser.WriteInt((int)value, _stateObj); } else if (SqlDbType.Money == _metaData.SqlDbType) { _stateObj.Parser.WriteInt((int)(value >> 0x20), _stateObj); _stateObj.Parser.WriteInt((int)value, _stateObj); } else { _stateObj.Parser.WriteLong(value, _stateObj); } } } // valid for SqlDbType.Real internal void SetSingle(Single value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetSingle)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(6, TdsEnums.SQLFLT4, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteFloat(value, _stateObj); } // valid for SqlDbType.Float internal void SetDouble(Double value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDouble)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLFLT8, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteDouble(value, _stateObj); } // valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range) internal void SetSqlDecimal(SqlDecimal value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetSqlDecimal)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(21, TdsEnums.SQLNUMERICN, 2, _stateObj); _stateObj.Parser.WriteByte(value.Precision, _stateObj); // propbytes: precision _stateObj.Parser.WriteByte(value.Scale, _stateObj); // propbytes: scale _stateObj.Parser.WriteSqlDecimal(value, _stateObj); } else { _stateObj.Parser.WriteByte(checked((byte)MetaType.MetaDecimal.FixedLength), _stateObj); // SmiMetaData's length and actual wire format's length are different _stateObj.Parser.WriteSqlDecimal(SqlDecimal.ConvertToPrecScale(value, _metaData.Precision, _metaData.Scale), _stateObj); } } // valid for DateTime, SmallDateTime, Date, DateTime2 internal void SetDateTime(DateTime value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDateTime)); if (SqlDbType.Variant == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, 8); _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLDATETIME, 0, _stateObj); _stateObj.Parser.WriteInt(dt.days, _stateObj); _stateObj.Parser.WriteInt(dt.time, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); if (SqlDbType.SmallDateTime == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, (byte)_metaData.MaxLength); Debug.Assert (0 <= dt.days && dt.days <= UInt16.MaxValue, "Invalid DateTime '" + value + "' for SmallDateTime"); _stateObj.Parser.WriteShort(dt.days, _stateObj); _stateObj.Parser.WriteShort(dt.time, _stateObj); } else if (SqlDbType.DateTime == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, (byte)_metaData.MaxLength); _stateObj.Parser.WriteInt(dt.days, _stateObj); _stateObj.Parser.WriteInt(dt.time, _stateObj); } else { // date and datetime2 int days = value.Subtract(DateTime.MinValue).Days; if (SqlDbType.DateTime2 == _metaData.SqlDbType) { Int64 time = value.TimeOfDay.Ticks / TdsEnums.TICKS_FROM_SCALE[_metaData.Scale]; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), (int)_metaData.MaxLength - 3, 0, _stateObj); } _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(days), 3, 0, _stateObj); } } } // valid for UniqueIdentifier internal void SetGuid(Guid value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetGuid)); byte[] bytes = value.ToByteArray(); Debug.Assert(SmiMetaData.DefaultUniqueIdentifier.MaxLength == bytes.Length, "Invalid length for guid bytes: " + bytes.Length); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(18, TdsEnums.SQLUNIQUEID, 0, _stateObj); } else { Debug.Assert(_metaData.MaxLength == bytes.Length, "Unexpected uniqueid metadata length: " + _metaData.MaxLength); _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteByteArray(bytes, bytes.Length, 0, _stateObj); } // valid for SqlDbType.Time internal void SetTimeSpan(TimeSpan value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetTime)); byte scale; byte length; if (SqlDbType.Variant == _metaData.SqlDbType) { scale = MetaType.MetaTime.Scale; length = (byte)MetaType.MetaTime.FixedLength; _stateObj.Parser.WriteSqlVariantHeader(8, TdsEnums.SQLTIME, 1, _stateObj); _stateObj.Parser.WriteByte(scale, _stateObj); //propbytes: scale } else { scale = _metaData.Scale; length = (byte)_metaData.MaxLength; _stateObj.Parser.WriteByte(length, _stateObj); } Int64 time = value.Ticks / TdsEnums.TICKS_FROM_SCALE[scale]; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), length, 0, _stateObj); } // valid for DateTimeOffset internal void SetDateTimeOffset(DateTimeOffset value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDateTimeOffset)); byte scale; byte length; if (SqlDbType.Variant == _metaData.SqlDbType) { scale = MetaType.MetaDateTimeOffset.Scale; length = (byte)MetaType.MetaDateTimeOffset.FixedLength; _stateObj.Parser.WriteSqlVariantHeader(13, TdsEnums.SQLDATETIMEOFFSET, 1, _stateObj); _stateObj.Parser.WriteByte(scale, _stateObj); //propbytes: scale } else { scale = _metaData.Scale; length = (byte)_metaData.MaxLength; _stateObj.Parser.WriteByte(length, _stateObj); } DateTime utcDateTime = value.UtcDateTime; Int64 time = utcDateTime.TimeOfDay.Ticks / TdsEnums.TICKS_FROM_SCALE[scale]; int days = utcDateTime.Subtract(DateTime.MinValue).Days; Int16 offset = (Int16)value.Offset.TotalMinutes; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), length - 5, 0, _stateObj); // time _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(days), 3, 0, _stateObj); // date _stateObj.Parser.WriteByte((byte)(offset & 0xff), _stateObj); // offset byte 1 _stateObj.Parser.WriteByte((byte)((offset >> 8) & 0xff), _stateObj); // offset byte 2 } internal void SetVariantType(SmiMetaData value) { Debug.Assert(null == _variantType, "Variant type can only be set once"); Debug.Assert(value != null && (value.SqlDbType == SqlDbType.Money || value.SqlDbType == SqlDbType.NVarChar), "Invalid variant type"); _variantType = value; } #endregion #region private methods [Conditional("DEBUG")] private void CheckSettingOffset(long offset) { #if DEBUG Debug.Assert(offset == _currentOffset, "Invalid offset passed. Should be: " + _currentOffset + ", but was: " + offset); #endif } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data.SqlClient { using Microsoft.SqlServer.Server; using System; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Data.SqlTypes; using System.Diagnostics; using System.Text; // TdsValueSetter handles writing a single value out to a TDS stream // This class can easily be extended to handle multiple versions of TDS by sub-classing and virtualizing // methods that have different formats or are not supported in one or the other version. internal class TdsValueSetter { #region Private fields private TdsParserStateObject _stateObj; // target to write to private SmiMetaData _metaData; // metadata describing value private bool _isPlp; // should this column be sent in PLP format? private bool _plpUnknownSent;// did we send initial UNKNOWN_LENGTH marker? private Encoder _encoder; // required for chunking character type data private SmiMetaData _variantType; // required for sql_variant #if DEBUG private int _currentOffset; // for chunking, verify that caller is using correct offsets #endif #endregion #region Exposed Construct/factory methods internal TdsValueSetter(TdsParserStateObject stateObj, SmiMetaData md) { _stateObj = stateObj; _metaData = md; _isPlp = MetaDataUtilsSmi.IsPlpFormat(md); _plpUnknownSent = false; _encoder = null; #if DEBUG _currentOffset = 0; #endif } #endregion #region Setters // Set value to null // valid for all types internal void SetDBNull() { Debug.Assert(!_plpUnknownSent, "Setting a column to null that we already stated sending!"); if (_isPlp) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_NULL, _stateObj); } else { switch(_metaData.SqlDbType) { case SqlDbType.BigInt: case SqlDbType.Bit: case SqlDbType.DateTime: case SqlDbType.Decimal: case SqlDbType.Float: case SqlDbType.Int: case SqlDbType.Money: case SqlDbType.Real: case SqlDbType.UniqueIdentifier: case SqlDbType.SmallDateTime: case SqlDbType.SmallInt: case SqlDbType.SmallMoney: case SqlDbType.TinyInt: case SqlDbType.Date: case SqlDbType.Time: case SqlDbType.DateTime2: case SqlDbType.DateTimeOffset: _stateObj.Parser.WriteByte(TdsEnums.FIXEDNULL, _stateObj); break; case SqlDbType.Binary: case SqlDbType.Char: case SqlDbType.Image: case SqlDbType.NChar: case SqlDbType.NText: case SqlDbType.NVarChar: case SqlDbType.Text: case SqlDbType.Timestamp: case SqlDbType.VarBinary: case SqlDbType.VarChar: _stateObj.Parser.WriteShort(TdsEnums.VARNULL, _stateObj); break; case SqlDbType.Udt: case SqlDbType.Xml: Debug.Assert(false, "PLP-only types shouldn't get to this point. Type: " + _metaData.SqlDbType); break; case SqlDbType.Variant: _stateObj.Parser.WriteInt(TdsEnums.FIXEDNULL, _stateObj); break; case SqlDbType.Structured: Debug.Assert(false, "Not yet implemented. Not needed until Structured UDTs"); break; default: Debug.Assert(false, "Unexpected SqlDbType: " + _metaData.SqlDbType); break; } } } // valid for SqlDbType.Bit internal void SetBoolean(Boolean value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBoolean)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(3, TdsEnums.SQLBIT, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } if (value) { _stateObj.Parser.WriteByte(1, _stateObj); } else { _stateObj.Parser.WriteByte(0, _stateObj); } } // valid for SqlDbType.TinyInt internal void SetByte(Byte value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetByte)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(3, TdsEnums.SQLINT1, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteByte(value, _stateObj); } // Semantics for SetBytes are to modify existing value, not overwrite // Use in combination with SetLength to ensure overwriting when necessary // valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml // (VarBinary assumed for variants) internal int SetBytes(long fieldOffset, byte[] buffer, int bufferOffset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBytes)); CheckSettingOffset(fieldOffset); SetBytesNoOffsetHandling(fieldOffset, buffer, bufferOffset, length); #if DEBUG _currentOffset += length; #endif return length; } private void SetBytesNoOffsetHandling(long fieldOffset, byte[] buffer, int bufferOffset, int length) { if (_isPlp) { if (!_plpUnknownSent) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, _stateObj); _plpUnknownSent = true; } // Write chunk length & chunk _stateObj.Parser.WriteInt(length, _stateObj); _stateObj.Parser.WriteByteArray(buffer, length, bufferOffset, _stateObj); } else { // Non-plp data must be sent in one chunk for now. #if DEBUG Debug.Assert(0 == _currentOffset, "SetBytes doesn't yet support chunking for non-plp data: " + _currentOffset); #endif Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4 + length, TdsEnums.SQLBIGVARBINARY, 2, _stateObj); } _stateObj.Parser.WriteShort(length, _stateObj); _stateObj.Parser.WriteByteArray(buffer, length, bufferOffset, _stateObj); } } internal void SetBytesLength(long length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetBytes)); CheckSettingOffset(length); if (0 == length) { if (_isPlp) { Debug.Assert(!_plpUnknownSent, "A plpUnknown has already been sent before setting length to zero."); _stateObj.Parser.WriteLong(0, _stateObj); _plpUnknownSent = true; } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4, TdsEnums.SQLBIGVARBINARY, 2, _stateObj); } _stateObj.Parser.WriteShort(0, _stateObj); } } if (_plpUnknownSent) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); _plpUnknownSent = false; } #if DEBUG // _currentOffset = 0; #endif } // Semantics for SetChars are to modify existing value, not overwrite // Use in combination with SetLength to ensure overwriting when necessary // valid for character types: Char, VarChar, Text, NChar, NVarChar, NText // (NVarChar and global clr collation assumed for variants) internal int SetChars(long fieldOffset, char[] buffer, int bufferOffset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetChars)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { if (null == _encoder) { _encoder = _stateObj.Parser._defaultEncoding.GetEncoder(); } byte[] bytes = new byte[_encoder.GetByteCount(buffer, bufferOffset, length, false)]; _encoder.GetBytes(buffer, bufferOffset, length, bytes, 0, false); SetBytesNoOffsetHandling(fieldOffset, bytes, 0, bytes.Length); } else { CheckSettingOffset(fieldOffset); // Send via PLP format if we can. if (_isPlp) { // Handle initial PLP markers if (!_plpUnknownSent) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, _stateObj); _plpUnknownSent = true; } // Write chunk length _stateObj.Parser.WriteInt(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } else { // Non-plp data must be sent in one chunk for now. #if DEBUG Debug.Assert(0 == _currentOffset, "SetChars doesn't yet support chunking for non-plp data: " + _currentOffset); #endif if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantValue(new String(buffer, bufferOffset, length), length, 0, _stateObj); } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); _stateObj.Parser.WriteShort(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } } } #if DEBUG _currentOffset += length; #endif return length; } internal void SetCharsLength(long length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetChars)); CheckSettingOffset(length); if (0 == length) { if (_isPlp) { Debug.Assert(!_plpUnknownSent, "A plpUnknown has already been sent before setting length to zero."); _stateObj.Parser.WriteLong(0, _stateObj); _plpUnknownSent = true; } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); _stateObj.Parser.WriteShort(0, _stateObj); } } if (_plpUnknownSent) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); _plpUnknownSent = false; } _encoder = null; #if DEBUG // _currentOffset = 0; #endif } // valid for character types: Char, VarChar, Text, NChar, NVarChar, NText internal void SetString(string value, int offset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetString)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { char[] chars = value.ToCharArray(offset, length); bytes = _stateObj.Parser._defaultEncoding.GetBytes(chars); } SetBytes(0, bytes, 0, bytes.Length); SetBytesLength(bytes.Length); } else if (SqlDbType.Variant == _metaData.SqlDbType) { Debug.Assert(null != _variantType && SqlDbType.NVarChar == _variantType.SqlDbType, "Invalid variant type"); SqlCollation collation = new SqlCollation(); collation.LCID = checked((int)_variantType.LocaleId); collation.SqlCompareOptions = _variantType.CompareOptions; if (length * ADP.CharSize > TdsEnums.TYPE_SIZE_LIMIT) { // send as varchar for length greater than 4000 byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value.ToCharArray(offset, length)); } _stateObj.Parser.WriteSqlVariantHeader(9 + bytes.Length, TdsEnums.SQLBIGVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.Parser.WriteByte(collation.sortId, _stateObj); // propbytes: collation.SortId _stateObj.Parser.WriteShort(bytes.Length, _stateObj); // propbyte: varlen _stateObj.Parser.WriteByteArray(bytes, bytes.Length, 0, _stateObj); } else { _stateObj.Parser.WriteSqlVariantHeader(9 + length * ADP.CharSize, TdsEnums.SQLNVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.Parser.WriteByte(collation.sortId, _stateObj); // propbytes: collation.SortId _stateObj.Parser.WriteShort(length * ADP.CharSize, _stateObj); // propbyte: varlen _stateObj.Parser.WriteString(value, length, offset, _stateObj); } _variantType = null; } else if (_isPlp) { // Send the string as a complete PLP chunk. _stateObj.Parser.WriteLong(length*ADP.CharSize, _stateObj); // PLP total length _stateObj.Parser.WriteInt(length*ADP.CharSize, _stateObj); // Chunk length _stateObj.Parser.WriteString(value, length, offset, _stateObj); // Data if (length != 0) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); // Terminator } } else { _stateObj.Parser.WriteShort(length*ADP.CharSize, _stateObj); _stateObj.Parser.WriteString(value, length, offset, _stateObj); } } // valid for SqlDbType.SmallInt internal void SetInt16(Int16 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt16)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(4, TdsEnums.SQLINT2, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteShort(value, _stateObj); } // valid for SqlDbType.Int internal void SetInt32(Int32 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt32)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(6, TdsEnums.SQLINT4, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteInt(value, _stateObj); } // valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney internal void SetInt64(Int64 value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetInt64)); if (SqlDbType.Variant == _metaData.SqlDbType) { if (null == _variantType) { _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLINT8, 0, _stateObj); _stateObj.Parser.WriteLong(value, _stateObj); } else { Debug.Assert(SqlDbType.Money == _variantType.SqlDbType, "Invalid variant type"); _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLMONEY, 0, _stateObj); _stateObj.Parser.WriteInt((int)(value >> 0x20), _stateObj); _stateObj.Parser.WriteInt((int)value, _stateObj); _variantType = null; } } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); if (SqlDbType.SmallMoney == _metaData.SqlDbType) { _stateObj.Parser.WriteInt((int)value, _stateObj); } else if (SqlDbType.Money == _metaData.SqlDbType) { _stateObj.Parser.WriteInt((int)(value >> 0x20), _stateObj); _stateObj.Parser.WriteInt((int)value, _stateObj); } else { _stateObj.Parser.WriteLong(value, _stateObj); } } } // valid for SqlDbType.Real internal void SetSingle(Single value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetSingle)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(6, TdsEnums.SQLFLT4, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteFloat(value, _stateObj); } // valid for SqlDbType.Float internal void SetDouble(Double value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDouble)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLFLT8, 0, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteDouble(value, _stateObj); } // valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range) internal void SetSqlDecimal(SqlDecimal value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetSqlDecimal)); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(21, TdsEnums.SQLNUMERICN, 2, _stateObj); _stateObj.Parser.WriteByte(value.Precision, _stateObj); // propbytes: precision _stateObj.Parser.WriteByte(value.Scale, _stateObj); // propbytes: scale _stateObj.Parser.WriteSqlDecimal(value, _stateObj); } else { _stateObj.Parser.WriteByte(checked((byte)MetaType.MetaDecimal.FixedLength), _stateObj); // SmiMetaData's length and actual wire format's length are different _stateObj.Parser.WriteSqlDecimal(SqlDecimal.ConvertToPrecScale(value, _metaData.Precision, _metaData.Scale), _stateObj); } } // valid for DateTime, SmallDateTime, Date, DateTime2 internal void SetDateTime(DateTime value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDateTime)); if (SqlDbType.Variant == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, 8); _stateObj.Parser.WriteSqlVariantHeader(10, TdsEnums.SQLDATETIME, 0, _stateObj); _stateObj.Parser.WriteInt(dt.days, _stateObj); _stateObj.Parser.WriteInt(dt.time, _stateObj); } else { _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); if (SqlDbType.SmallDateTime == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, (byte)_metaData.MaxLength); Debug.Assert (0 <= dt.days && dt.days <= UInt16.MaxValue, "Invalid DateTime '" + value + "' for SmallDateTime"); _stateObj.Parser.WriteShort(dt.days, _stateObj); _stateObj.Parser.WriteShort(dt.time, _stateObj); } else if (SqlDbType.DateTime == _metaData.SqlDbType) { TdsDateTime dt = MetaType.FromDateTime(value, (byte)_metaData.MaxLength); _stateObj.Parser.WriteInt(dt.days, _stateObj); _stateObj.Parser.WriteInt(dt.time, _stateObj); } else { // date and datetime2 int days = value.Subtract(DateTime.MinValue).Days; if (SqlDbType.DateTime2 == _metaData.SqlDbType) { Int64 time = value.TimeOfDay.Ticks / TdsEnums.TICKS_FROM_SCALE[_metaData.Scale]; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), (int)_metaData.MaxLength - 3, 0, _stateObj); } _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(days), 3, 0, _stateObj); } } } // valid for UniqueIdentifier internal void SetGuid(Guid value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetGuid)); byte[] bytes = value.ToByteArray(); Debug.Assert(SmiMetaData.DefaultUniqueIdentifier.MaxLength == bytes.Length, "Invalid length for guid bytes: " + bytes.Length); if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantHeader(18, TdsEnums.SQLUNIQUEID, 0, _stateObj); } else { Debug.Assert(_metaData.MaxLength == bytes.Length, "Unexpected uniqueid metadata length: " + _metaData.MaxLength); _stateObj.Parser.WriteByte((byte)_metaData.MaxLength, _stateObj); } _stateObj.Parser.WriteByteArray(bytes, bytes.Length, 0, _stateObj); } // valid for SqlDbType.Time internal void SetTimeSpan(TimeSpan value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetTime)); byte scale; byte length; if (SqlDbType.Variant == _metaData.SqlDbType) { scale = MetaType.MetaTime.Scale; length = (byte)MetaType.MetaTime.FixedLength; _stateObj.Parser.WriteSqlVariantHeader(8, TdsEnums.SQLTIME, 1, _stateObj); _stateObj.Parser.WriteByte(scale, _stateObj); //propbytes: scale } else { scale = _metaData.Scale; length = (byte)_metaData.MaxLength; _stateObj.Parser.WriteByte(length, _stateObj); } Int64 time = value.Ticks / TdsEnums.TICKS_FROM_SCALE[scale]; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), length, 0, _stateObj); } // valid for DateTimeOffset internal void SetDateTimeOffset(DateTimeOffset value) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDateTimeOffset)); byte scale; byte length; if (SqlDbType.Variant == _metaData.SqlDbType) { scale = MetaType.MetaDateTimeOffset.Scale; length = (byte)MetaType.MetaDateTimeOffset.FixedLength; _stateObj.Parser.WriteSqlVariantHeader(13, TdsEnums.SQLDATETIMEOFFSET, 1, _stateObj); _stateObj.Parser.WriteByte(scale, _stateObj); //propbytes: scale } else { scale = _metaData.Scale; length = (byte)_metaData.MaxLength; _stateObj.Parser.WriteByte(length, _stateObj); } DateTime utcDateTime = value.UtcDateTime; Int64 time = utcDateTime.TimeOfDay.Ticks / TdsEnums.TICKS_FROM_SCALE[scale]; int days = utcDateTime.Subtract(DateTime.MinValue).Days; Int16 offset = (Int16)value.Offset.TotalMinutes; _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(time), length - 5, 0, _stateObj); // time _stateObj.Parser.WriteByteArray(BitConverter.GetBytes(days), 3, 0, _stateObj); // date _stateObj.Parser.WriteByte((byte)(offset & 0xff), _stateObj); // offset byte 1 _stateObj.Parser.WriteByte((byte)((offset >> 8) & 0xff), _stateObj); // offset byte 2 } internal void SetVariantType(SmiMetaData value) { Debug.Assert(null == _variantType, "Variant type can only be set once"); Debug.Assert(value != null && (value.SqlDbType == SqlDbType.Money || value.SqlDbType == SqlDbType.NVarChar), "Invalid variant type"); _variantType = value; } #endregion #region private methods [Conditional("DEBUG")] private void CheckSettingOffset(long offset) { #if DEBUG Debug.Assert(offset == _currentOffset, "Invalid offset passed. Should be: " + _currentOffset + ", but was: " + offset); #endif } #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
- ExplicitDiscriminatorMap.cs
- DataGrid.cs
- ListGeneralPage.cs
- WmfPlaceableFileHeader.cs
- CompiledELinqQueryState.cs
- DBConnectionString.cs
- ScriptResourceInfo.cs
- EntityDataSourceContextDisposingEventArgs.cs
- XmlDataDocument.cs
- ModulesEntry.cs
- ApplicationFileCodeDomTreeGenerator.cs
- ClientRequest.cs
- SqlRowUpdatingEvent.cs
- CryptoHandle.cs
- NavigationPropertySingletonExpression.cs
- PenLineJoinValidation.cs
- CalendarDay.cs
- HyperLink.cs
- SqlProcedureAttribute.cs
- OrderByExpression.cs
- OdbcDataReader.cs
- GatewayIPAddressInformationCollection.cs
- QilChoice.cs
- ColorAnimationBase.cs
- OperatingSystemVersionCheck.cs
- DbModificationCommandTree.cs
- SafeArrayRankMismatchException.cs
- CoreSwitches.cs
- Size.cs
- Polygon.cs
- XamlParser.cs
- TreeBuilder.cs
- CommandLineParser.cs
- PersonalizationAdministration.cs
- DocumentEventArgs.cs
- SqlInfoMessageEvent.cs
- PointLight.cs
- TemplatedWizardStep.cs
- AssemblyCache.cs
- MembershipPasswordException.cs
- XamlInterfaces.cs
- IgnoreFileBuildProvider.cs
- IfAction.cs
- MenuItem.cs
- FileLoadException.cs
- ByteKeyFrameCollection.cs
- PixelShader.cs
- DetailsViewInsertedEventArgs.cs
- SignedPkcs7.cs
- TableItemProviderWrapper.cs
- UpDownBase.cs
- CryptoApi.cs
- InstancePersistence.cs
- GeneratedView.cs
- ThreadStartException.cs
- ShapeTypeface.cs
- SqlFactory.cs
- NumericPagerField.cs
- LinkedList.cs
- DeferredTextReference.cs
- WebPartEditorOkVerb.cs
- NullReferenceException.cs
- UnsafeMethods.cs
- datacache.cs
- RelationshipNavigation.cs
- RegistryPermission.cs
- PropertyGridCommands.cs
- DbMetaDataFactory.cs
- CompressEmulationStream.cs
- TemplatedMailWebEventProvider.cs
- OciEnlistContext.cs
- Substitution.cs
- cache.cs
- ZipIOBlockManager.cs
- Documentation.cs
- PermissionListSet.cs
- DocumentStatusResources.cs
- SoapRpcServiceAttribute.cs
- Vector3D.cs
- ResourceDisplayNameAttribute.cs
- Cursors.cs
- TypedReference.cs
- ClientUrlResolverWrapper.cs
- XsdValidatingReader.cs
- VerificationException.cs
- CollectionsUtil.cs
- ScrollPatternIdentifiers.cs
- Calendar.cs
- WmlPhoneCallAdapter.cs
- SqlDependencyListener.cs
- AudioStateChangedEventArgs.cs
- NonVisualControlAttribute.cs
- ControlEvent.cs
- XamlInt32CollectionSerializer.cs
- DataViewSettingCollection.cs
- DetailsViewInsertEventArgs.cs
- RecognizedWordUnit.cs
- SecurityContextTokenValidationException.cs
- MenuItem.cs
- DropShadowBitmapEffect.cs