Ejemplo n.º 1
0
        internal object FromBytes(byte[] bytes, int offset, int length)
        {
            switch (_DataType)
            {
            case SqlDbType.BigInt:
                switch (length)
                {
                case 1: return((long)bytes[offset]);

                case 2: return((long)BitUtil.ToUInt16(bytes, offset, true));

                case 3: return((long)BitUtil.ToUInt24(bytes, offset, true));

                case 4: return((long)BitUtil.ToUInt32(bytes, offset, true));

                case 8: return(BitUtil.ToInt64(bytes, offset, true));

                default: throw new Exception("Unrecognized length for bigint: " + length);
                }

            case SqlDbType.Binary:
                byte[] binaryBytes = new byte[DataTypeLength.Value];
                Array.Copy(bytes, offset, binaryBytes, 0, length);
                return(binaryBytes);

            case SqlDbType.VarBinary:
                byte[] varBinaryBytes = new byte[length];
                Array.Copy(bytes, offset, varBinaryBytes, 0, length);
                return(varBinaryBytes);

            case SqlDbType.Bit: return((bytes[offset] & 1) != 0);

            case SqlDbType.Char:
                byte[] charBytes = new byte[DataTypeLength.Value];
                Array.Copy(bytes, offset, charBytes, 0, length);
                //go ahead and set each extra 32's (spaces) if length is shorted
                for (int i = length; i < DataTypeLength.Value; i++)
                {
                    charBytes[i] = 32;
                }
                return(Encoding.UTF8.GetString(charBytes));

            case SqlDbType.VarChar:
                byte[] varCharBytes = new byte[length];
                Array.Copy(bytes, offset, varCharBytes, 0, length);
                return(Encoding.UTF8.GetString(varCharBytes));

            case SqlDbType.Date: return(new DateTime().AddDays(BitUtil.ToInt32(bytes, offset + 4, true)));

            case SqlDbType.DateTime:
                if (length < 8)
                {
                    byte[] dateBytes = new byte[8];
                    for (int i = 0; i < 8; i++)
                    {
                        if (i < length)
                        {
                            dateBytes[i] = bytes[offset + i];
                        }
                        else
                        {
                            dateBytes[i] = 0;
                        }
                    }
                    return(new DateTime(1900, 1, 1).AddDays(BitUtil.ToInt32(dateBytes, 4, true)).
                           AddMilliseconds(THREE_AND_ONE_THIRD * BitUtil.ToInt32(dateBytes, 0, true)));
                }
                else
                {
                    return(new DateTime(1900, 1, 1).AddDays(BitUtil.ToInt32(bytes, offset + 4, true)).
                           AddMilliseconds(THREE_AND_ONE_THIRD * BitUtil.ToInt32(bytes, offset, true)));
                }

            case SqlDbType.DateTime2:
                return(new DateTime().AddDays(BitUtil.ToInt32(bytes, offset + 8, true)).
                       AddMilliseconds(1000d / Math.Pow(10, Scale.Value) * BitUtil.ToInt64(bytes, offset, true)));

            case SqlDbType.DateTimeOffset: return("DateTimeOffset not supported");

            case SqlDbType.Decimal:
                //when data type length is less than the data type length, we must pad with zeroes
                if (length < DataTypeLength.Value)
                {
                    byte[] decimalBytes = new byte[offset + DataTypeLength.Value];
                    Array.Copy(bytes, offset, decimalBytes, offset, length);
                    bytes  = decimalBytes;
                    length = DataTypeLength.Value;
                }
                int[] bits = new int[4];
                bits[0] = BitUtil.ToInt32(bytes, offset + 1, true);
                bits[1] = length >= 9 ? BitUtil.ToInt32(bytes, offset + 5, true) : 0;
                bits[2] = length >= 13 ? BitUtil.ToInt32(bytes, offset + 9, true) : 0;
                bits[3] = length >= 17 ? BitUtil.ToInt32(bytes, offset + 13, true) : 0;
                //sometimes this is bigger than C#'s max precision/scale of 28 so just return SqlDecimal
                if (_Precision > 28 || _Scale > 28)
                {
                    return(new SqlDecimal(_Precision.Value, (byte)_Scale, bytes[offset] == 1, bits));
                }
                else
                {
                    return(new SqlDecimal(_Precision.Value, (byte)_Scale, bytes[offset] == 1, bits).Value);
                }

            case SqlDbType.Float:
                switch (length)
                {
                case 7:
                    return(BitUtil.ToDouble(new byte[] {
                        bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3],
                        bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], 64
                    }, 0, true));

                case 8: return(BitUtil.ToDouble(bytes, offset, true));

                default: throw new Exception("Unrecognized float length: " + length);
                }

            case SqlDbType.Image: return("Image not supported");

            case SqlDbType.Int:
                switch (length)
                {
                case 1: return((int)bytes[offset]);

                case 2: return((int)BitUtil.ToUInt16(bytes, offset, true));

                case 3: return((int)BitUtil.ToUInt24(bytes, offset, true));

                case 4: return(BitUtil.ToInt32(bytes, offset, true));

                default: throw new Exception("Unrecognized int length : " + length);
                }

            case SqlDbType.Money:
                if (length < 8)
                {
                    byte[] moneyBytes = new byte[8];
                    for (int i = 0; i < 8; i++)
                    {
                        if (i < length)
                        {
                            moneyBytes[i] = bytes[offset + i];
                        }
                        else
                        {
                            moneyBytes[i] = (byte)(i == 2 ? 1 : 0);
                        }
                    }
                    return(BitUtil.ToInt64(moneyBytes, 0, true) / 10000d);
                }
                return(BitUtil.ToInt64(bytes, offset, true) / 10000d);

            case SqlDbType.NChar:
                byte[] ncharBytes = new byte[DataTypeLength.Value];
                Array.Copy(bytes, offset, ncharBytes, 0, length);
                //go ahead and set each extra 32's (spaces) if length is shorted
                for (int i = length; i < DataTypeLength.Value; i++)
                {
                    ncharBytes[i] = (byte)(i % 2 == 1 ? 0 : 32);
                }
                return(Encoding.Unicode.GetString(ncharBytes));

            case SqlDbType.NVarChar:
                //if it's an odd number, we have to add a zero to the end
                int    nvarCharLength = length + (length % 2);
                byte[] nvarCharBytes  = new byte[nvarCharLength];
                Array.Copy(bytes, offset, nvarCharBytes, 0, length);
                return(Encoding.Unicode.GetString(nvarCharBytes));

            case SqlDbType.NText: return("NText not supported");

            case SqlDbType.Real: return(BitUtil.ToSingle(bytes, offset, true));

            case SqlDbType.SmallDateTime:
                return(new DateTime(1900, 1, 1).AddDays(BitUtil.ToUInt16(bytes, offset + 2, true)).
                       AddMinutes(BitUtil.ToUInt16(bytes, offset, true)));

            case SqlDbType.SmallInt:
                return(length == 1 ? (short)bytes[offset] : BitUtil.ToInt16(bytes, offset, true));

            case SqlDbType.SmallMoney:
                switch (length)
                {
                case 3: return(BitUtil.ToInt32(new byte[] {
                        bytes[offset], bytes[offset + 1], bytes[offset + 2], 0
                    }, 0, true) / 10000d);

                case 4: return(BitUtil.ToInt32(bytes, offset, true) / 10000d);

                default: throw new Exception("Unrecognized length for small money: " + length);
                }

            case SqlDbType.Structured: return("Structured not supported");

            case SqlDbType.Text: return("Text not supported");

            case SqlDbType.Time:
                return(TimeSpan.FromMilliseconds(1000d / Math.Pow(10, Scale.Value) * BitUtil.ToInt64(bytes, offset, true)));

            case SqlDbType.Timestamp: return("Timestamp not supported");

            case SqlDbType.TinyInt: return(bytes[offset]);

            case SqlDbType.Udt: return("UDT's not supported");

            case SqlDbType.UniqueIdentifier:
                byte[] guid = new byte[16];
                Array.Copy(bytes, offset, guid, 0, 16);
                return(new Guid(guid));

            case SqlDbType.Variant: return("Variant not supported");

            case SqlDbType.Xml: return("Xml not supported");

            default: throw new NotImplementedException(_DataType + " not implemented");
            }
        }