Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / DataOracleClient / System / Data / OracleClient / OracleDateTime.cs / 2 / OracleDateTime.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Data.OracleClient { using System; using System.Data.SqlTypes; using System.Data.Common; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.Text; //--------------------------------------------------------------------- // OracleDateTime // // This class implements support for Oracle's DATE internal data // type, which is really contains both Date and Time values (but // doesn't contain fractional seconds). // // It also implements support for the Oracle 9i 'TIMESTAMP', // 'TIMESTAMP WITH LOCAL TIME ZONE' and 'TIMESTAMP WITH TIME ZONE' // internal data types. // [StructLayout(LayoutKind.Sequential, Pack=1)] public struct OracleDateTime : IComparable, INullable { private const int MaxOracleFSecPrecision = 9; private byte[] _value; // null == value is null; length(7) == date; length(11) == timestamp; length(13) == timestampwithtz private const byte x_DATE_Length = 7; private const byte x_TIMESTAMP_Length = 11; private const byte x_TIMESTAMP_WITH_TIMEZONE_Length = 13; private const int FractionalSecondsPerTick = 100; public static readonly OracleDateTime MaxValue = new OracleDateTime(DateTime.MaxValue); public static readonly OracleDateTime MinValue = new OracleDateTime(DateTime.MinValue); public static readonly OracleDateTime Null = new OracleDateTime(true); // Construct from nothing -- the value will be null private OracleDateTime(bool isNull) { _value = null; } // Construct from System.DateTime type public OracleDateTime (DateTime dt) { _value = new byte[x_TIMESTAMP_Length]; Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } public OracleDateTime (Int64 ticks) { _value = new byte[x_TIMESTAMP_Length]; DateTime dt = new DateTime(ticks); Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } public OracleDateTime (int year, int month, int day) : this (year, month, day, 0, 0, 0, 0) {} public OracleDateTime (int year, int month, int day, Calendar calendar) : this (year, month, day, 0, 0, 0, 0, calendar) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second) : this (year, month, day, hour, minute, second, 0) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar) : this (year, month, day, hour, minute, second, 0, calendar) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond) { _value = new byte[x_TIMESTAMP_Length]; // WebData 109872 - we really need to validate this value, because // Oracle doesn't. If the year is negative, we just don't bother, // because DateTime won't support it. new DateTime((year < 0) ? 0 : year, month, (year < 0) ? 1 : day, hour, minute, second, millisecond); Pack (_value, year, month, day, hour, minute, second, (int)(millisecond * TimeSpan.TicksPerMillisecond) * FractionalSecondsPerTick); } public OracleDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar) { _value = new byte[x_TIMESTAMP_Length]; DateTime dt = new DateTime(year, month, day, hour, minute, second, millisecond, calendar); Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } // Copy constructor public OracleDateTime (OracleDateTime from) { _value = new byte[from._value.Length]; from._value.CopyTo(_value, 0); } // (internal) construct OracleDateTime: // * from parameter binding buffer for DATE type only // * from row fetch buffer: DATE and INT_TIMESTAMP* types internal OracleDateTime(NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { _value = GetBytesFromBuffer(buffer, valueOffset, lengthOffset, metaType, connection); } // (internal) construct from Oracle descriptor for INT_TIMESTAMP types for parameter binding only internal OracleDateTime(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { _value = GetBytesFromDescriptor(dateTimeDescriptor, metaType, connection); } static private void Pack (byte[] dateval, int year, int month, int day, int hour, int minute, int second, int fsecs) { // DEVNOTE: undoubtedly, this is Intel byte order specific, but how // do I verify what Oracle needs on a non Intel machine? dateval[0] = (byte)((year / 100) + 100); dateval[1] = (byte)((year % 100) + 100); dateval[2] = (byte)(month); dateval[3] = (byte)(day); dateval[4] = (byte)(hour + 1); dateval[5] = (byte)(minute + 1); dateval[6] = (byte)(second + 1); dateval[7] = (byte)((fsecs >> 24)); dateval[8] = (byte)((fsecs >> 16) & 0xff); dateval[9] = (byte)((fsecs >> 8) & 0xff); dateval[10]= (byte)(fsecs & 0xff); } static private int Unpack (byte[] dateval, out int year, out int month, out int day, out int hour, out int minute, out int second, out int fsec) { int tzh, tzm; // DEVNOTE: undoubtedly, this is Intel byte order specific, but how // do I verify what Oracle needs on a non Intel machine? year =(((int)dateval[0] - 100) * 100) + ((int)dateval[1] - 100); month = (int)dateval[2]; day = (int)dateval[3]; hour = (int)dateval[4] - 1; minute = (int)dateval[5] - 1; second = (int)dateval[6] - 1; if (x_DATE_Length == dateval.Length) { fsec = tzh = tzm = 0; } else { fsec = (int)dateval[7] << 24 | (int)dateval[8] << 16 | (int)dateval[9] << 8 | (int)dateval[10] ; if (x_TIMESTAMP_Length == dateval.Length) { tzh = tzm = 0; } else { tzh = dateval[11] - 20; tzm = dateval[12] - 60; } } if (x_TIMESTAMP_WITH_TIMEZONE_Length == dateval.Length) { // DEVNOTE: I'm not really all that excited about the fact that I'm // constructing a System.DateTime value to unpack, but if you // look at what is involved in adjusting the value for the // timezone, it turns into the same thing that DateTime does. DateTime utcValue = (new DateTime(year, month, day, hour, minute, second)) + (new TimeSpan(tzh, tzm, 0)); year = utcValue.Year; month = utcValue.Month; day = utcValue.Day; hour = utcValue.Hour; minute = utcValue.Minute; // Seconds and Fractional Seconds aren't affected by time zones (yet!) } return dateval.Length; } public bool IsNull { get { return (null == _value); } } public DateTime Value { get { if (IsNull) { throw ADP.DataIsNull(); } DateTime result = ToDateTime(_value); return result; } } public int Year { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return year; } } public int Month { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return month; } } public int Day { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return day; } } public int Hour { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return hour; } } public int Minute { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return minute; } } public int Second { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return second; } } public int Millisecond { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); int milliseconds = (int)((fsec / FractionalSecondsPerTick) / TimeSpan.TicksPerMillisecond); return milliseconds; } } public int CompareTo( object obj ) { if (obj.GetType() == typeof(OracleDateTime)) { OracleDateTime odt = (OracleDateTime)obj; // If both values are Null, consider them equal. // Otherwise, Null is less than anything. if (IsNull) { return odt.IsNull ? 0 : -1; } if (odt.IsNull) { return 1; } // Neither value is null, do the comparison, but take the Timezone into account. int year1, month1, day1, hour1, minute1, second1, fsec1; int year2, month2, day2, hour2, minute2, second2, fsec2; Unpack( _value, out year1, out month1, out day1, out hour1, out minute1, out second1, out fsec1); Unpack( odt._value, out year2, out month2, out day2, out hour2, out minute2, out second2, out fsec2); int delta; delta = (year1 - year2); if (0 != delta) return delta; delta = (month1 - month2); if (0 != delta) return delta; delta = (day1 - day2); if (0 != delta) return delta; delta = (hour1 - hour2); if (0 != delta) return delta; delta = (minute1 - minute2); if (0 != delta) return delta; delta = (second1 - second2); if (0 != delta) return delta; delta = (fsec1 - fsec2); if (0 != delta) return delta; return 0; } throw ADP.WrongType(obj.GetType(), typeof(OracleDateTime)); } public override bool Equals(object value) { if (value is OracleDateTime) { return (this == (OracleDateTime)value).Value; } else { return false; } } // returns the raw data bytes from the OCI's OracleDateTime descriptor buffer for INT_TIMESTAMP* types, // taking the binding type into account and adjusting it for the server time zones, as appropriate. static internal byte[] GetBytesFromDescriptor(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { // allocate the result buffer uint ociBytes; OCI.DATATYPE ociType = metaType.OciType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: ociBytes = x_TIMESTAMP_Length; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; } byte[] result = new byte[ociBytes]; uint templen = (uint)ociBytes; OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); // read the byte array from descriptor int rc = UnsafeNativeMethods.OCIDateTimeToArray( connection.EnvironmentHandle, connection.ErrorHandle, dateTimeDescriptor, tz, // used for LTZ only - to be compatible with 2.0 RTM, we do not set the offset timezone to client's timezone, so it is not used in calculations result, ref templen, MaxOracleFSecPrecision // use the max fsec precision ); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } // fill timezone, depending on the type if (OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType) { // user connection to get the server's timezone TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; result[11] = (byte)(tzadjust.Hours + 20); result[12] = (byte)(tzadjust.Minutes + 60); } else if (OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType) { // use OCI API to retrieve the timezone information from the descriptor itself sbyte tzHour; sbyte tzMin; rc = UnsafeNativeMethods.OCIDateTimeGetTimeZoneOffset( connection.EnvironmentHandle, connection.ErrorHandle, dateTimeDescriptor, out tzHour, out tzMin); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } result[11] = (byte)(tzHour + 20); result[12] = (byte)(tzMin + 60); } return result; } static internal byte[] GetBytesFromBuffer (NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { // Static method to return the raw data bytes from the row/parameter // buffer, taking the binding type into account and adjusting it for // the server time zones, as appropriate. uint ociBytes; OCI.DATATYPE ociType = metaType.OciType; short length = buffer.ReadInt16(lengthOffset); switch (ociType) { case OCI.DATATYPE.DATE: ociBytes = x_DATE_Length; break; case OCI.DATATYPE.INT_TIMESTAMP: ociBytes = x_TIMESTAMP_Length; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; } byte[] result = new byte[ociBytes]; // NOTE: will zero the data buffer.ReadBytes(valueOffset, result, 0, length); if (OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType) { TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; result[11] = (byte)(tzadjust.Hours + 20); result[12] = (byte)(tzadjust.Minutes + 60); } else if (OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType && 0x80 < result[11]) { // WebData 114105 - as it happens, Oracle has two formats for // TIMESTAMP WITH TIME ZONE -- one is the format that includes // the time zone offset hours and minutes in the value, the other // includes some funky value that they translate into the name // of the time zone when they format it. The first format is // relatively straight-forward, the latter is unintelligable, but // it does seem to be valid. Since Oracle knows what to do with // those, we simply hand it to Oracle and ask them to convert it // to something we can use. // // NOTE, that Oracle requires that we give them an interval for // conversion from TIMESTAMP_LTZ, but we have already pre- // qualified that we don't have one of those, so we simply // create an empty interval instead and pass it on. int rc; OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); OciDateTimeDescriptor ts = new OciDateTimeDescriptor(connection.EnvironmentHandle, OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ); sbyte tzHour; sbyte tzMin; rc = UnsafeNativeMethods.OCIDateTimeFromArray( connection.EnvironmentHandle, connection.ErrorHandle, result, ociBytes, (byte)OCI.DATATYPE.TIMESTAMP_TZ, ts, tz, 0); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } rc = UnsafeNativeMethods.OCIDateTimeGetTimeZoneOffset( connection.EnvironmentHandle, connection.ErrorHandle, ts, out tzHour, out tzMin); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } result[11] = (byte)(tzHour + 20); result[12] = (byte)(tzMin + 60); } return result; } public override int GetHashCode() { int retval = IsNull ? 0 : _value.GetHashCode(); return retval; } // used to deserialize DATE and INT_TIMESTAMP types from native buffer and convert it to DateTime static internal DateTime MarshalToDateTime(NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { byte[] rawValue = GetBytesFromBuffer(buffer, valueOffset, lengthOffset, metaType, connection); DateTime result = ToDateTime(rawValue); return result; } // used to serialize DATE type only into native buffer for parameter binding static internal int MarshalDateToNative(object value, NativeBuffer buffer, int offset, OCI.DATATYPE ociType, OracleConnection connection) { byte[] from; if (value is OracleDateTime) { from = ((OracleDateTime)value)._value; } else { DateTime dt = (DateTime)value; from = new byte[x_TIMESTAMP_Length]; // Pack requires at least x_TIMESTAMP_Length // pack the date and time only, fsec is not used in DATE type Pack(from, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0); } int ociBytes = x_DATE_Length; buffer.WriteBytes(offset, from, 0, ociBytes); return ociBytes; } // used to deserialize INT_TIMESTAMP* values from OCI's OracleDateTime descriptor and construct CLR's DateTime for them static internal DateTime MarshalTimestampToDateTime(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { byte[] rawValue = GetBytesFromDescriptor(dateTimeDescriptor, metaType, connection); DateTime result = ToDateTime(rawValue); return result; } // creates empty OCI's OracleDateTime descriptor to be used for INT_TIMESTAMP* values serialization // caller should ensure ociType validity before calling this method static internal OciDateTimeDescriptor CreateEmptyDescriptor(OCI.DATATYPE ociType, OracleConnection connection) { // convert DATATYPE to HTYPE OCI.HTYPE dbType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP; break; case OCI.DATATYPE.INT_TIMESTAMP_TZ: dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType, "unrecognized type"); dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ; break; } OciDateTimeDescriptor descriptor = new OciDateTimeDescriptor(connection.EnvironmentHandle, dbType); return descriptor; } // creates OCI's OracleDateTime descriptor and fills it with given DateTime or OracleDateTime value // this method is used with INT_TIMESTAMP* values only, caller should ensure ociType validity before calling it static internal OciDateTimeDescriptor CreateDescriptor(OCI.DATATYPE ociType, OracleConnection connection, object value) { // this array will be used as an input to OCIDateTimeFromArray to construct the OCI Datetime descriptor byte[] from; if (value is OracleDateTime) { from = ((OracleDateTime)value)._value; } else { // this will raise cast exception if value is neither OracleDateTime nor DateTime (backward compatibility) DateTime dt = (DateTime)value; OracleDateTime temp = new OracleDateTime(dt); from = temp._value; } OCI.DATATYPE dbType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: dbType = OCI.DATATYPE.TIMESTAMP; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: dbType = OCI.DATATYPE.TIMESTAMP_LTZ; break; case OCI.DATATYPE.INT_TIMESTAMP_TZ: default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); dbType = OCI.DATATYPE.TIMESTAMP_TZ; // for TIMESTAMP with time zone: we have to specify explicitly the timezone to preserve full backward compatibility with 2.0 RTM // if the input byte array does not have time zone information in it, create a new byte array and explicitly initialize the time zone // from the Oracle's database time zone (dbtimezone). TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; if (from.Length < x_TIMESTAMP_WITH_TIMEZONE_Length) { byte[] valueWithTZ = new byte[x_TIMESTAMP_WITH_TIMEZONE_Length]; Buffer.BlockCopy(from, 0, valueWithTZ, 0, from.Length); from = valueWithTZ; // set the timezone into array from[11] = (byte)(20 + tzadjust.Hours); from[12] = (byte)(60 + tzadjust.Minutes); } break; } // create empty descriptor OciDateTimeDescriptor descriptor = CreateEmptyDescriptor(ociType, connection); OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); // NOTE: VSTS 225565: we've tried to use OCIDateTimeConstruct API, but it looks like that API ignores the timezone argument for TIMESTAMP_TZ type. // Using OCIDateTimeFromArray we can set the timezone information into the descriptor int rc = UnsafeNativeMethods.OCIDateTimeFromArray( connection.EnvironmentHandle, connection.ErrorHandle, from, (uint)from.Length, (byte)dbType, descriptor, tz, // used for LTZ only - to be compatible with 2.0 RTM, we do not set the offset timezone to client's timezone, so it is not used in calculations MaxOracleFSecPrecision // use the max fsec precision ); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } return descriptor; } internal bool HasTimeZoneInfo { get { return _value != null && _value.Length >= x_TIMESTAMP_WITH_TIMEZONE_Length; } } internal bool HasTimeInfo { get { return _value != null && _value.Length >= x_TIMESTAMP_Length; } } public static OracleDateTime Parse(string s) { // Rather than figure out which formats, etc, we just simplify our // life and convert this to a DateTime, which we can use to build // the real Oracle Date from. DateTime datetime = DateTime.Parse(s, null); return new OracleDateTime(datetime); } static private DateTime ToDateTime(byte[] rawValue) { int year, month, day, hour, minute, second, fsec; int length = Unpack( rawValue, out year, out month, out day, out hour, out minute, out second, out fsec); DateTime result = new DateTime(year, month, day, hour, minute, second); if (length > x_DATE_Length && fsec > FractionalSecondsPerTick) { // DEVNOTE: Yes, there's a mismatch in the precision between Oracle, // (which has 9 digits) and System.DateTime (which has 7 // digits); All the other providers truncate the precision, // so we do as well. result = result.AddTicks((long)fsec / FractionalSecondsPerTick); } return result; } public override string ToString() { if (IsNull) { return ADP.NullString; } string retval = Value.ToString((IFormatProvider)null); return retval; } public static OracleBoolean Equals(OracleDateTime x, OracleDateTime y) { // Alternative method for operator == return (x == y); } public static OracleBoolean GreaterThan(OracleDateTime x, OracleDateTime y) { // Alternative method for operator > return (x > y); } public static OracleBoolean GreaterThanOrEqual(OracleDateTime x, OracleDateTime y) { // Alternative method for operator >= return (x >= y); } public static OracleBoolean LessThan(OracleDateTime x, OracleDateTime y) { // Alternative method for operator < return (x < y); } public static OracleBoolean LessThanOrEqual(OracleDateTime x, OracleDateTime y) { // Alternative method for operator <= return (x <= y); } public static OracleBoolean NotEquals(OracleDateTime x, OracleDateTime y) { // Alternative method for operator != return (x != y); } public static explicit operator DateTime(OracleDateTime x) { if (x.IsNull) { throw ADP.DataIsNull(); } return x.Value; } public static explicit operator OracleDateTime(string x) { return OracleDateTime.Parse(x); } public static OracleBoolean operator== (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) == 0); } public static OracleBoolean operator> (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) > 0); } public static OracleBoolean operator>= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) >= 0); } public static OracleBoolean operator< (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) < 0); } public static OracleBoolean operator<= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) <= 0); } public static OracleBoolean operator!= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) != 0); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Data.OracleClient { using System; using System.Data.SqlTypes; using System.Data.Common; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.Text; //--------------------------------------------------------------------- // OracleDateTime // // This class implements support for Oracle's DATE internal data // type, which is really contains both Date and Time values (but // doesn't contain fractional seconds). // // It also implements support for the Oracle 9i 'TIMESTAMP', // 'TIMESTAMP WITH LOCAL TIME ZONE' and 'TIMESTAMP WITH TIME ZONE' // internal data types. // [StructLayout(LayoutKind.Sequential, Pack=1)] public struct OracleDateTime : IComparable, INullable { private const int MaxOracleFSecPrecision = 9; private byte[] _value; // null == value is null; length(7) == date; length(11) == timestamp; length(13) == timestampwithtz private const byte x_DATE_Length = 7; private const byte x_TIMESTAMP_Length = 11; private const byte x_TIMESTAMP_WITH_TIMEZONE_Length = 13; private const int FractionalSecondsPerTick = 100; public static readonly OracleDateTime MaxValue = new OracleDateTime(DateTime.MaxValue); public static readonly OracleDateTime MinValue = new OracleDateTime(DateTime.MinValue); public static readonly OracleDateTime Null = new OracleDateTime(true); // Construct from nothing -- the value will be null private OracleDateTime(bool isNull) { _value = null; } // Construct from System.DateTime type public OracleDateTime (DateTime dt) { _value = new byte[x_TIMESTAMP_Length]; Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } public OracleDateTime (Int64 ticks) { _value = new byte[x_TIMESTAMP_Length]; DateTime dt = new DateTime(ticks); Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } public OracleDateTime (int year, int month, int day) : this (year, month, day, 0, 0, 0, 0) {} public OracleDateTime (int year, int month, int day, Calendar calendar) : this (year, month, day, 0, 0, 0, 0, calendar) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second) : this (year, month, day, hour, minute, second, 0) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar) : this (year, month, day, hour, minute, second, 0, calendar) {} public OracleDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond) { _value = new byte[x_TIMESTAMP_Length]; // WebData 109872 - we really need to validate this value, because // Oracle doesn't. If the year is negative, we just don't bother, // because DateTime won't support it. new DateTime((year < 0) ? 0 : year, month, (year < 0) ? 1 : day, hour, minute, second, millisecond); Pack (_value, year, month, day, hour, minute, second, (int)(millisecond * TimeSpan.TicksPerMillisecond) * FractionalSecondsPerTick); } public OracleDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar) { _value = new byte[x_TIMESTAMP_Length]; DateTime dt = new DateTime(year, month, day, hour, minute, second, millisecond, calendar); Pack (_value, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)(dt.Ticks % TimeSpan.TicksPerSecond) * FractionalSecondsPerTick); } // Copy constructor public OracleDateTime (OracleDateTime from) { _value = new byte[from._value.Length]; from._value.CopyTo(_value, 0); } // (internal) construct OracleDateTime: // * from parameter binding buffer for DATE type only // * from row fetch buffer: DATE and INT_TIMESTAMP* types internal OracleDateTime(NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { _value = GetBytesFromBuffer(buffer, valueOffset, lengthOffset, metaType, connection); } // (internal) construct from Oracle descriptor for INT_TIMESTAMP types for parameter binding only internal OracleDateTime(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { _value = GetBytesFromDescriptor(dateTimeDescriptor, metaType, connection); } static private void Pack (byte[] dateval, int year, int month, int day, int hour, int minute, int second, int fsecs) { // DEVNOTE: undoubtedly, this is Intel byte order specific, but how // do I verify what Oracle needs on a non Intel machine? dateval[0] = (byte)((year / 100) + 100); dateval[1] = (byte)((year % 100) + 100); dateval[2] = (byte)(month); dateval[3] = (byte)(day); dateval[4] = (byte)(hour + 1); dateval[5] = (byte)(minute + 1); dateval[6] = (byte)(second + 1); dateval[7] = (byte)((fsecs >> 24)); dateval[8] = (byte)((fsecs >> 16) & 0xff); dateval[9] = (byte)((fsecs >> 8) & 0xff); dateval[10]= (byte)(fsecs & 0xff); } static private int Unpack (byte[] dateval, out int year, out int month, out int day, out int hour, out int minute, out int second, out int fsec) { int tzh, tzm; // DEVNOTE: undoubtedly, this is Intel byte order specific, but how // do I verify what Oracle needs on a non Intel machine? year =(((int)dateval[0] - 100) * 100) + ((int)dateval[1] - 100); month = (int)dateval[2]; day = (int)dateval[3]; hour = (int)dateval[4] - 1; minute = (int)dateval[5] - 1; second = (int)dateval[6] - 1; if (x_DATE_Length == dateval.Length) { fsec = tzh = tzm = 0; } else { fsec = (int)dateval[7] << 24 | (int)dateval[8] << 16 | (int)dateval[9] << 8 | (int)dateval[10] ; if (x_TIMESTAMP_Length == dateval.Length) { tzh = tzm = 0; } else { tzh = dateval[11] - 20; tzm = dateval[12] - 60; } } if (x_TIMESTAMP_WITH_TIMEZONE_Length == dateval.Length) { // DEVNOTE: I'm not really all that excited about the fact that I'm // constructing a System.DateTime value to unpack, but if you // look at what is involved in adjusting the value for the // timezone, it turns into the same thing that DateTime does. DateTime utcValue = (new DateTime(year, month, day, hour, minute, second)) + (new TimeSpan(tzh, tzm, 0)); year = utcValue.Year; month = utcValue.Month; day = utcValue.Day; hour = utcValue.Hour; minute = utcValue.Minute; // Seconds and Fractional Seconds aren't affected by time zones (yet!) } return dateval.Length; } public bool IsNull { get { return (null == _value); } } public DateTime Value { get { if (IsNull) { throw ADP.DataIsNull(); } DateTime result = ToDateTime(_value); return result; } } public int Year { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return year; } } public int Month { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return month; } } public int Day { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return day; } } public int Hour { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return hour; } } public int Minute { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return minute; } } public int Second { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); return second; } } public int Millisecond { get { if (IsNull) { throw ADP.DataIsNull(); } int year, month, day, hour, minute, second, fsec; Unpack( _value, out year, out month, out day, out hour, out minute, out second, out fsec); int milliseconds = (int)((fsec / FractionalSecondsPerTick) / TimeSpan.TicksPerMillisecond); return milliseconds; } } public int CompareTo( object obj ) { if (obj.GetType() == typeof(OracleDateTime)) { OracleDateTime odt = (OracleDateTime)obj; // If both values are Null, consider them equal. // Otherwise, Null is less than anything. if (IsNull) { return odt.IsNull ? 0 : -1; } if (odt.IsNull) { return 1; } // Neither value is null, do the comparison, but take the Timezone into account. int year1, month1, day1, hour1, minute1, second1, fsec1; int year2, month2, day2, hour2, minute2, second2, fsec2; Unpack( _value, out year1, out month1, out day1, out hour1, out minute1, out second1, out fsec1); Unpack( odt._value, out year2, out month2, out day2, out hour2, out minute2, out second2, out fsec2); int delta; delta = (year1 - year2); if (0 != delta) return delta; delta = (month1 - month2); if (0 != delta) return delta; delta = (day1 - day2); if (0 != delta) return delta; delta = (hour1 - hour2); if (0 != delta) return delta; delta = (minute1 - minute2); if (0 != delta) return delta; delta = (second1 - second2); if (0 != delta) return delta; delta = (fsec1 - fsec2); if (0 != delta) return delta; return 0; } throw ADP.WrongType(obj.GetType(), typeof(OracleDateTime)); } public override bool Equals(object value) { if (value is OracleDateTime) { return (this == (OracleDateTime)value).Value; } else { return false; } } // returns the raw data bytes from the OCI's OracleDateTime descriptor buffer for INT_TIMESTAMP* types, // taking the binding type into account and adjusting it for the server time zones, as appropriate. static internal byte[] GetBytesFromDescriptor(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { // allocate the result buffer uint ociBytes; OCI.DATATYPE ociType = metaType.OciType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: ociBytes = x_TIMESTAMP_Length; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; } byte[] result = new byte[ociBytes]; uint templen = (uint)ociBytes; OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); // read the byte array from descriptor int rc = UnsafeNativeMethods.OCIDateTimeToArray( connection.EnvironmentHandle, connection.ErrorHandle, dateTimeDescriptor, tz, // used for LTZ only - to be compatible with 2.0 RTM, we do not set the offset timezone to client's timezone, so it is not used in calculations result, ref templen, MaxOracleFSecPrecision // use the max fsec precision ); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } // fill timezone, depending on the type if (OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType) { // user connection to get the server's timezone TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; result[11] = (byte)(tzadjust.Hours + 20); result[12] = (byte)(tzadjust.Minutes + 60); } else if (OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType) { // use OCI API to retrieve the timezone information from the descriptor itself sbyte tzHour; sbyte tzMin; rc = UnsafeNativeMethods.OCIDateTimeGetTimeZoneOffset( connection.EnvironmentHandle, connection.ErrorHandle, dateTimeDescriptor, out tzHour, out tzMin); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } result[11] = (byte)(tzHour + 20); result[12] = (byte)(tzMin + 60); } return result; } static internal byte[] GetBytesFromBuffer (NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { // Static method to return the raw data bytes from the row/parameter // buffer, taking the binding type into account and adjusting it for // the server time zones, as appropriate. uint ociBytes; OCI.DATATYPE ociType = metaType.OciType; short length = buffer.ReadInt16(lengthOffset); switch (ociType) { case OCI.DATATYPE.DATE: ociBytes = x_DATE_Length; break; case OCI.DATATYPE.INT_TIMESTAMP: ociBytes = x_TIMESTAMP_Length; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); ociBytes = x_TIMESTAMP_WITH_TIMEZONE_Length; break; } byte[] result = new byte[ociBytes]; // NOTE: will zero the data buffer.ReadBytes(valueOffset, result, 0, length); if (OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType) { TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; result[11] = (byte)(tzadjust.Hours + 20); result[12] = (byte)(tzadjust.Minutes + 60); } else if (OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType && 0x80 < result[11]) { // WebData 114105 - as it happens, Oracle has two formats for // TIMESTAMP WITH TIME ZONE -- one is the format that includes // the time zone offset hours and minutes in the value, the other // includes some funky value that they translate into the name // of the time zone when they format it. The first format is // relatively straight-forward, the latter is unintelligable, but // it does seem to be valid. Since Oracle knows what to do with // those, we simply hand it to Oracle and ask them to convert it // to something we can use. // // NOTE, that Oracle requires that we give them an interval for // conversion from TIMESTAMP_LTZ, but we have already pre- // qualified that we don't have one of those, so we simply // create an empty interval instead and pass it on. int rc; OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); OciDateTimeDescriptor ts = new OciDateTimeDescriptor(connection.EnvironmentHandle, OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ); sbyte tzHour; sbyte tzMin; rc = UnsafeNativeMethods.OCIDateTimeFromArray( connection.EnvironmentHandle, connection.ErrorHandle, result, ociBytes, (byte)OCI.DATATYPE.TIMESTAMP_TZ, ts, tz, 0); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } rc = UnsafeNativeMethods.OCIDateTimeGetTimeZoneOffset( connection.EnvironmentHandle, connection.ErrorHandle, ts, out tzHour, out tzMin); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } result[11] = (byte)(tzHour + 20); result[12] = (byte)(tzMin + 60); } return result; } public override int GetHashCode() { int retval = IsNull ? 0 : _value.GetHashCode(); return retval; } // used to deserialize DATE and INT_TIMESTAMP types from native buffer and convert it to DateTime static internal DateTime MarshalToDateTime(NativeBuffer buffer, int valueOffset, int lengthOffset, MetaType metaType, OracleConnection connection) { byte[] rawValue = GetBytesFromBuffer(buffer, valueOffset, lengthOffset, metaType, connection); DateTime result = ToDateTime(rawValue); return result; } // used to serialize DATE type only into native buffer for parameter binding static internal int MarshalDateToNative(object value, NativeBuffer buffer, int offset, OCI.DATATYPE ociType, OracleConnection connection) { byte[] from; if (value is OracleDateTime) { from = ((OracleDateTime)value)._value; } else { DateTime dt = (DateTime)value; from = new byte[x_TIMESTAMP_Length]; // Pack requires at least x_TIMESTAMP_Length // pack the date and time only, fsec is not used in DATE type Pack(from, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0); } int ociBytes = x_DATE_Length; buffer.WriteBytes(offset, from, 0, ociBytes); return ociBytes; } // used to deserialize INT_TIMESTAMP* values from OCI's OracleDateTime descriptor and construct CLR's DateTime for them static internal DateTime MarshalTimestampToDateTime(OciDateTimeDescriptor dateTimeDescriptor, MetaType metaType, OracleConnection connection) { byte[] rawValue = GetBytesFromDescriptor(dateTimeDescriptor, metaType, connection); DateTime result = ToDateTime(rawValue); return result; } // creates empty OCI's OracleDateTime descriptor to be used for INT_TIMESTAMP* values serialization // caller should ensure ociType validity before calling this method static internal OciDateTimeDescriptor CreateEmptyDescriptor(OCI.DATATYPE ociType, OracleConnection connection) { // convert DATATYPE to HTYPE OCI.HTYPE dbType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP; break; case OCI.DATATYPE.INT_TIMESTAMP_TZ: dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_LTZ == ociType, "unrecognized type"); dbType = OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ; break; } OciDateTimeDescriptor descriptor = new OciDateTimeDescriptor(connection.EnvironmentHandle, dbType); return descriptor; } // creates OCI's OracleDateTime descriptor and fills it with given DateTime or OracleDateTime value // this method is used with INT_TIMESTAMP* values only, caller should ensure ociType validity before calling it static internal OciDateTimeDescriptor CreateDescriptor(OCI.DATATYPE ociType, OracleConnection connection, object value) { // this array will be used as an input to OCIDateTimeFromArray to construct the OCI Datetime descriptor byte[] from; if (value is OracleDateTime) { from = ((OracleDateTime)value)._value; } else { // this will raise cast exception if value is neither OracleDateTime nor DateTime (backward compatibility) DateTime dt = (DateTime)value; OracleDateTime temp = new OracleDateTime(dt); from = temp._value; } OCI.DATATYPE dbType; switch (ociType) { case OCI.DATATYPE.INT_TIMESTAMP: dbType = OCI.DATATYPE.TIMESTAMP; break; case OCI.DATATYPE.INT_TIMESTAMP_LTZ: dbType = OCI.DATATYPE.TIMESTAMP_LTZ; break; case OCI.DATATYPE.INT_TIMESTAMP_TZ: default: Debug.Assert(OCI.DATATYPE.INT_TIMESTAMP_TZ == ociType, "unrecognized type"); dbType = OCI.DATATYPE.TIMESTAMP_TZ; // for TIMESTAMP with time zone: we have to specify explicitly the timezone to preserve full backward compatibility with 2.0 RTM // if the input byte array does not have time zone information in it, create a new byte array and explicitly initialize the time zone // from the Oracle's database time zone (dbtimezone). TimeSpan tzadjust = connection.ServerTimeZoneAdjustmentToUTC; if (from.Length < x_TIMESTAMP_WITH_TIMEZONE_Length) { byte[] valueWithTZ = new byte[x_TIMESTAMP_WITH_TIMEZONE_Length]; Buffer.BlockCopy(from, 0, valueWithTZ, 0, from.Length); from = valueWithTZ; // set the timezone into array from[11] = (byte)(20 + tzadjust.Hours); from[12] = (byte)(60 + tzadjust.Minutes); } break; } // create empty descriptor OciDateTimeDescriptor descriptor = CreateEmptyDescriptor(ociType, connection); OciIntervalDescriptor tz = new OciIntervalDescriptor(connection.EnvironmentHandle); // NOTE: VSTS 225565: we've tried to use OCIDateTimeConstruct API, but it looks like that API ignores the timezone argument for TIMESTAMP_TZ type. // Using OCIDateTimeFromArray we can set the timezone information into the descriptor int rc = UnsafeNativeMethods.OCIDateTimeFromArray( connection.EnvironmentHandle, connection.ErrorHandle, from, (uint)from.Length, (byte)dbType, descriptor, tz, // used for LTZ only - to be compatible with 2.0 RTM, we do not set the offset timezone to client's timezone, so it is not used in calculations MaxOracleFSecPrecision // use the max fsec precision ); if (0 != rc) { connection.CheckError(connection.ErrorHandle, rc); } return descriptor; } internal bool HasTimeZoneInfo { get { return _value != null && _value.Length >= x_TIMESTAMP_WITH_TIMEZONE_Length; } } internal bool HasTimeInfo { get { return _value != null && _value.Length >= x_TIMESTAMP_Length; } } public static OracleDateTime Parse(string s) { // Rather than figure out which formats, etc, we just simplify our // life and convert this to a DateTime, which we can use to build // the real Oracle Date from. DateTime datetime = DateTime.Parse(s, null); return new OracleDateTime(datetime); } static private DateTime ToDateTime(byte[] rawValue) { int year, month, day, hour, minute, second, fsec; int length = Unpack( rawValue, out year, out month, out day, out hour, out minute, out second, out fsec); DateTime result = new DateTime(year, month, day, hour, minute, second); if (length > x_DATE_Length && fsec > FractionalSecondsPerTick) { // DEVNOTE: Yes, there's a mismatch in the precision between Oracle, // (which has 9 digits) and System.DateTime (which has 7 // digits); All the other providers truncate the precision, // so we do as well. result = result.AddTicks((long)fsec / FractionalSecondsPerTick); } return result; } public override string ToString() { if (IsNull) { return ADP.NullString; } string retval = Value.ToString((IFormatProvider)null); return retval; } public static OracleBoolean Equals(OracleDateTime x, OracleDateTime y) { // Alternative method for operator == return (x == y); } public static OracleBoolean GreaterThan(OracleDateTime x, OracleDateTime y) { // Alternative method for operator > return (x > y); } public static OracleBoolean GreaterThanOrEqual(OracleDateTime x, OracleDateTime y) { // Alternative method for operator >= return (x >= y); } public static OracleBoolean LessThan(OracleDateTime x, OracleDateTime y) { // Alternative method for operator < return (x < y); } public static OracleBoolean LessThanOrEqual(OracleDateTime x, OracleDateTime y) { // Alternative method for operator <= return (x <= y); } public static OracleBoolean NotEquals(OracleDateTime x, OracleDateTime y) { // Alternative method for operator != return (x != y); } public static explicit operator DateTime(OracleDateTime x) { if (x.IsNull) { throw ADP.DataIsNull(); } return x.Value; } public static explicit operator OracleDateTime(string x) { return OracleDateTime.Parse(x); } public static OracleBoolean operator== (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) == 0); } public static OracleBoolean operator> (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) > 0); } public static OracleBoolean operator>= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) >= 0); } public static OracleBoolean operator< (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) < 0); } public static OracleBoolean operator<= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) <= 0); } public static OracleBoolean operator!= (OracleDateTime x, OracleDateTime y) { return (x.IsNull || y.IsNull) ? OracleBoolean.Null : new OracleBoolean(x.CompareTo(y) != 0); } } } // 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
- SocketElement.cs
- ExternalException.cs
- followingsibling.cs
- _FtpControlStream.cs
- Serializer.cs
- HttpDateParse.cs
- ConfigurationValues.cs
- HeaderedContentControl.cs
- DataSourceNameHandler.cs
- StringPropertyBuilder.cs
- ThemeInfoAttribute.cs
- AssemblyUtil.cs
- DataGridViewLinkCell.cs
- ClientTargetSection.cs
- ThreadAttributes.cs
- ReliabilityContractAttribute.cs
- XmlWhitespace.cs
- TagPrefixAttribute.cs
- DbDeleteCommandTree.cs
- ListBox.cs
- SQLInt64.cs
- Utils.cs
- RegexCode.cs
- CompleteWizardStep.cs
- TemplatePropertyEntry.cs
- ColumnMapProcessor.cs
- CompilationPass2TaskInternal.cs
- HttpProfileBase.cs
- TokenCreationException.cs
- OutputScopeManager.cs
- ImageInfo.cs
- UserPreferenceChangingEventArgs.cs
- RotationValidation.cs
- _CommandStream.cs
- HexParser.cs
- SetUserPreferenceRequest.cs
- Exception.cs
- Stackframe.cs
- LinqDataView.cs
- XmlSerializerNamespaces.cs
- Track.cs
- XsltFunctions.cs
- URLString.cs
- LocalizationParserHooks.cs
- ConvertEvent.cs
- TraceRecord.cs
- SecurityTokenValidationException.cs
- ConnectionPoint.cs
- ItemType.cs
- BitStream.cs
- BezierSegment.cs
- KerberosSecurityTokenAuthenticator.cs
- WmpBitmapEncoder.cs
- DataObjectFieldAttribute.cs
- DisableDpiAwarenessAttribute.cs
- XmlEncodedRawTextWriter.cs
- DataSourceUtil.cs
- SizeConverter.cs
- Setter.cs
- x509store.cs
- BufferAllocator.cs
- RelatedImageListAttribute.cs
- Point3D.cs
- ToolStripDropDownButton.cs
- CloudCollection.cs
- StoryFragments.cs
- FileChangeNotifier.cs
- CellQuery.cs
- BitmapImage.cs
- TextWriter.cs
- ImageListStreamer.cs
- ProtectedConfigurationSection.cs
- SqlNodeAnnotations.cs
- ExtendedPropertiesHandler.cs
- ActivitySurrogateSelector.cs
- BitSet.cs
- AppDomainAttributes.cs
- oledbmetadatacollectionnames.cs
- MessageQueue.cs
- ExpressionBuilderContext.cs
- LeftCellWrapper.cs
- LocalIdKeyIdentifierClause.cs
- FunctionImportElement.cs
- XmlIncludeAttribute.cs
- CorrelationManager.cs
- RenderingEventArgs.cs
- PocoPropertyAccessorStrategy.cs
- ToolStripPanelCell.cs
- FontDialog.cs
- DataGridViewCellCancelEventArgs.cs
- DataListItemCollection.cs
- EnumCodeDomSerializer.cs
- Maps.cs
- MenuItem.cs
- WebPartConnectionsDisconnectVerb.cs
- SqlDataSourceCache.cs
- SignatureResourceHelper.cs
- SetStateEventArgs.cs
- StylusButtonEventArgs.cs
- ClientSideProviderDescription.cs