DataStorage.cs source code in C# .NET

Source code for the .NET framework in C#



/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / Common / DataStorage.cs / 1305376 / DataStorage.cs

//     Copyright (c) Microsoft Corporation.  All rights reserved.
// [....] 
// [....]
namespace System.Data.Common {
    using System; 
    using System.Collections;
    using System.Collections.Generic;
    using System.Data.SqlTypes;
    using System.Diagnostics; 
    using System.Xml;
    using System.Xml.Serialization; 
    internal enum StorageType {
        Empty       = TypeCode.Empty, // 0 
        Object      = TypeCode.Object,
        DBNull      = TypeCode.DBNull,
        Boolean     = TypeCode.Boolean,
        Char        = TypeCode.Char, 
        SByte       = TypeCode.SByte,
        Byte        = TypeCode.Byte, 
        Int16       = TypeCode.Int16, 
        UInt16      = TypeCode.UInt16,
        Int32       = TypeCode.Int32, 
        UInt32      = TypeCode.UInt32,
        Int64       = TypeCode.Int64,
        UInt64      = TypeCode.UInt64,
        Single      = TypeCode.Single, 
        Double      = TypeCode.Double,
        Decimal     = TypeCode.Decimal, // 15 
        DateTime    = TypeCode.DateTime, // 16 
        TimeSpan    = 17,
        String      = TypeCode.String, // 18 
        Guid        = 19,

        ByteArray   = 20,
        CharArray   = 21, 
        Type        = 22,
        DateTimeOffset = 23, 
        BigInteger  = 24, 
        Uri         = 25,
        SqlBinary, // SqlTypes should remain at the end for IsSqlType checking
//        SqlXml, 
    abstract internal class DataStorage {

        // for Whidbey 40426, searching down the Type[] is about 20% faster than using a Dictionary
        // must keep in same order as enum StorageType 
        private static readonly Type[] StorageClassType = new Type[] {

//            typeof(SqlXml), 
        internal readonly DataColumn Column; 
        internal readonly DataTable Table;
        internal readonly Type DataType; 
        internal readonly StorageType StorageTypeCode;
        private System.Collections.BitArray dbNullBits;

        private readonly object DefaultValue; 
        internal readonly object NullValue;
        internal readonly bool IsCloneable; 
        internal readonly bool IsCustomDefinedType;
        internal readonly bool IsStringType; 
        internal readonly bool IsValueType;

        protected DataStorage(DataColumn column, Type type, object defaultValue)
            : this(column, type, defaultValue, DBNull.Value, false) { 
        protected DataStorage(DataColumn column, Type type, object defaultValue, object nullValue) 
            : this(column, type, defaultValue, nullValue, false) {

        protected DataStorage(DataColumn column, Type type, object defaultValue, object nullValue, bool isICloneable) {
            Column = column;
            Table = column.Table; 
            DataType = type;
            StorageTypeCode = GetStorageType(type); 
            DefaultValue = defaultValue; 
            NullValue = nullValue;
            IsCloneable = isICloneable; 
            IsCustomDefinedType = IsTypeCustomType(StorageTypeCode);
            IsStringType = ((StorageType.String == StorageTypeCode) || (StorageType.SqlString == StorageTypeCode));
            IsValueType = DetermineIfValueType(StorageTypeCode, type);

        internal DataSetDateTime DateTimeMode { 
            get { 
                return Column.DateTimeMode;

        internal IFormatProvider FormatProvider {
            get { 
                return Table.FormatProvider;

        public virtual Object Aggregate(int[] recordNos, AggregateType kind) { 
            if (AggregateType.Count == kind) {
                return this.AggregateCount(recordNos);
            return null; 
        public object AggregateCount(int[] recordNos) { 
            int count = 0;
            for (int i = 0; i < recordNos.Length; i++) { 
                if (!this.dbNullBits.Get(recordNos[i]))
            return count; 
        protected int CompareBits(int recordNo1, int recordNo2) { 
            bool recordNo1Null = this.dbNullBits.Get(recordNo1);
            bool recordNo2Null = this.dbNullBits.Get(recordNo2); 
            if (recordNo1Null ^ recordNo2Null) {
                if (recordNo1Null)
                    return -1;
                    return 1;
            return 0;

        public abstract int Compare(int recordNo1, int recordNo2);

        // only does comparision, expect value to be of the correct type 
        public abstract int CompareValueTo(int recordNo1, object value);
        // only does conversion with support for reference null 
        public virtual object ConvertValue(object value) {
            return value; 

        protected void CopyBits(int srcRecordNo, int dstRecordNo) {
            this.dbNullBits.Set(dstRecordNo, this.dbNullBits.Get(srcRecordNo)); 
        abstract public void Copy(int recordNo1, int recordNo2); 

        abstract public Object Get(int recordNo); 

        protected Object GetBits(int recordNo) {
            if (this.dbNullBits.Get(recordNo)) {
                return NullValue; 
            return DefaultValue; 

        virtual public int GetStringLength(int record) { 
            System.Diagnostics.Debug.Assert(false, "not a String or SqlString column");
            return Int32.MaxValue;
        protected bool HasValue(int recordNo) {
            return !this.dbNullBits.Get(recordNo); 

        public virtual bool IsNull(int recordNo) { 
            return this.dbNullBits.Get(recordNo);

        // convert (may not support reference null) and store the value 
        abstract public void Set(int recordNo, Object value);
        protected void SetNullBit(int recordNo, bool flag) { 
            this.dbNullBits.Set(recordNo, flag);

        virtual public void SetCapacity(int capacity) {
            if (null == this.dbNullBits) {
                this.dbNullBits = new BitArray(capacity); 
            else { 
                this.dbNullBits.Length = capacity; 

        abstract public object ConvertXmlToObject(string s);
        public virtual object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) {
            return ConvertXmlToObject(xmlReader.Value); 
        abstract public string ConvertObjectToXml(object value); 
        public virtual void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) {
            xmlWriter.WriteString(ConvertObjectToXml(value));// should it be NO OP? 

        public static DataStorage CreateStorage(DataColumn column, Type dataType) {
            StorageType typeCode = GetStorageType(dataType); 
            if ((StorageType.Empty == typeCode) && (null != dataType)) {
                if (typeof(INullable).IsAssignableFrom(dataType)) { // Udt, OracleTypes 
                    return new SqlUdtStorage(column, dataType); 
                else { 
                    return new ObjectStorage(column, dataType); // non-nullable non-primitives
            switch (typeCode) {
            case StorageType.Empty: throw ExceptionBuilder.InvalidStorageType(TypeCode.Empty); 
            case StorageType.DBNull: throw ExceptionBuilder.InvalidStorageType(TypeCode.DBNull); 
            case StorageType.Object: return new ObjectStorage(column, dataType);
            case StorageType.Boolean: return new BooleanStorage(column); 
            case StorageType.Char: return new CharStorage(column);
            case StorageType.SByte: return new SByteStorage(column);
            case StorageType.Byte: return new ByteStorage(column);
            case StorageType.Int16: return new Int16Storage(column); 
            case StorageType.UInt16: return new UInt16Storage(column);
            case StorageType.Int32: return new Int32Storage(column); 
            case StorageType.UInt32: return new UInt32Storage(column); 
            case StorageType.Int64: return new Int64Storage(column);
            case StorageType.UInt64: return new UInt64Storage(column); 
            case StorageType.Single: return new SingleStorage(column);
            case StorageType.Double: return new DoubleStorage(column);
            case StorageType.Decimal: return new DecimalStorage(column);
            case StorageType.DateTime: return new DateTimeStorage(column); 
            case StorageType.TimeSpan: return new TimeSpanStorage(column);
            case StorageType.String: return new StringStorage(column); 
            case StorageType.Guid: return new ObjectStorage(column, dataType); 

            case StorageType.ByteArray: return new ObjectStorage(column, dataType); 
            case StorageType.CharArray: return new ObjectStorage(column, dataType);
            case StorageType.Type: return new ObjectStorage(column, dataType);
            case StorageType.DateTimeOffset: return new DateTimeOffsetStorage(column);
            case StorageType.BigInteger: return new BigIntegerStorage(column); 
            case StorageType.Uri: return new ObjectStorage(column, dataType);
            case StorageType.SqlBinary: return new SqlBinaryStorage(column); 
            case StorageType.SqlBoolean: return new SqlBooleanStorage(column);
            case StorageType.SqlByte: return new SqlByteStorage(column); 
            case StorageType.SqlBytes: return new SqlBytesStorage(column);
            case StorageType.SqlChars: return new SqlCharsStorage(column);
            case StorageType.SqlDateTime: return new SqlDateTimeStorage(column); //???/ what to do
            case StorageType.SqlDecimal: return new SqlDecimalStorage(column); 
            case StorageType.SqlDouble: return new SqlDoubleStorage(column);
            case StorageType.SqlGuid: return new SqlGuidStorage(column); 
            case StorageType.SqlInt16: return new SqlInt16Storage(column); 
            case StorageType.SqlInt32: return new SqlInt32Storage(column);
            case StorageType.SqlInt64: return new SqlInt64Storage(column); 
            case StorageType.SqlMoney: return new SqlMoneyStorage(column);
            case StorageType.SqlSingle: return new SqlSingleStorage(column);
            case StorageType.SqlString: return new SqlStringStorage(column);
            //            case StorageType.SqlXml:         return new SqlXmlStorage(column); 

                System.Diagnostics.Debug.Assert(false, "shouldn't be here"); 
                goto case StorageType.Object;

        internal static StorageType GetStorageType(Type dataType) {
            for (int i = 0; i < StorageClassType.Length; ++i) { 
                if (dataType == StorageClassType[i]) {
                    return (StorageType)i; 
            TypeCode tcode = Type.GetTypeCode(dataType); 
            if (TypeCode.Object != tcode) { // enum -> Int64/Int32/Int16/Byte
                return (StorageType)tcode;
            return StorageType.Empty; 
        internal static Type GetTypeStorage(StorageType storageType) { 
            return StorageClassType[(int)storageType];

        internal static bool IsTypeCustomType(Type type) {
            return IsTypeCustomType(GetStorageType(type));

        internal static bool IsTypeCustomType(StorageType typeCode) { 
            return ((StorageType.Object == typeCode) || (StorageType.Empty == typeCode) || (StorageType.CharArray == typeCode)); 
        internal static bool IsSqlType(StorageType storageType) {
            return (StorageType.SqlBinary <= storageType);
        public static bool IsSqlType(Type dataType) {
            for (int i = (int)StorageType.SqlBinary; i < StorageClassType.Length; ++i) { 
                if (dataType == StorageClassType[i]) { 
                    return true;
            return false;
        private static bool DetermineIfValueType(StorageType typeCode, Type dataType) {
            bool result; 
            switch (typeCode) { 
            case StorageType.Boolean:
            case StorageType.Char: 
            case StorageType.SByte:
            case StorageType.Byte:
            case StorageType.Int16:
            case StorageType.UInt16: 
            case StorageType.Int32:
            case StorageType.UInt32: 
            case StorageType.Int64: 
            case StorageType.UInt64:
            case StorageType.Single: 
            case StorageType.Double:
            case StorageType.Decimal:
            case StorageType.DateTime:
            case StorageType.DateTimeOffset: 
            case StorageType.BigInteger:
            case StorageType.TimeSpan: 
            case StorageType.Guid: 
            case StorageType.SqlBinary:
            case StorageType.SqlBoolean: 
            case StorageType.SqlByte:
            case StorageType.SqlDateTime:
            case StorageType.SqlDecimal:
            case StorageType.SqlDouble: 
            case StorageType.SqlGuid:
            case StorageType.SqlInt16: 
            case StorageType.SqlInt32: 
            case StorageType.SqlInt64:
            case StorageType.SqlMoney: 
            case StorageType.SqlSingle:
            case StorageType.SqlString:
                result = true;

            case StorageType.String: 
            case StorageType.ByteArray: 
            case StorageType.CharArray:
            case StorageType.Type: 
            case StorageType.Uri:
            case StorageType.SqlBytes:
            case StorageType.SqlChars:
                result = false; 
                result = dataType.IsValueType;
            Debug.Assert(result == dataType.IsValueType, "typeCode mismatches dataType");
            return result;

        internal static void ImplementsInterfaces( 
                                    StorageType typeCode, 
                                    Type dataType,
                                    out bool sqlType, 
                                    out bool nullable,
                                    out bool xmlSerializable,
                                    out bool changeTracking,
                                    out bool revertibleChangeTracking) 
            Debug.Assert(typeCode == GetStorageType(dataType), "typeCode mismatches dataType"); 
            if (IsSqlType(typeCode)) { 
                sqlType = true;
                nullable = true; 
                changeTracking = false;
                revertibleChangeTracking = false;
                xmlSerializable = true;
            else if (StorageType.Empty != typeCode) {
                sqlType = false; 
                nullable = false; 
                changeTracking = false;
                revertibleChangeTracking = false; 
                xmlSerializable = false;
            else {
                sqlType = false; 
                nullable = typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(dataType);
                changeTracking = typeof(System.ComponentModel.IChangeTracking).IsAssignableFrom(dataType); 
                revertibleChangeTracking = typeof(System.ComponentModel.IRevertibleChangeTracking).IsAssignableFrom(dataType); 
                xmlSerializable = typeof(System.Xml.Serialization.IXmlSerializable).IsAssignableFrom(dataType);
            Debug.Assert(nullable == typeof(System.Data.SqlTypes.INullable).IsAssignableFrom(dataType), "INullable");
            Debug.Assert(changeTracking == typeof(System.ComponentModel.IChangeTracking).IsAssignableFrom(dataType), "IChangeTracking");
            Debug.Assert(revertibleChangeTracking == typeof(System.ComponentModel.IRevertibleChangeTracking).IsAssignableFrom(dataType), "IRevertibleChangeTracking");
            Debug.Assert(xmlSerializable == typeof(System.Xml.Serialization.IXmlSerializable).IsAssignableFrom(dataType), "IXmlSerializable"); 
        internal static bool ImplementsINullableValue(StorageType typeCode, Type dataType) { 
            Debug.Assert(typeCode == GetStorageType(dataType), "typeCode mismatches dataType");
            return ((StorageType.Empty == typeCode) && dataType.IsGenericType && (dataType.GetGenericTypeDefinition() == typeof(System.Nullable<>))); 

        public static bool IsObjectNull(object value) {
            return ((null == value) || (DBNull.Value == value) || IsObjectSqlNull(value)); 
        public static bool IsObjectSqlNull(object value) { 
            INullable inullable = (value as INullable);
            return ((null != inullable) && inullable.IsNull); 

        internal object GetEmptyStorageInternal(int recordCount) {
            return GetEmptyStorage(recordCount); 
        internal void CopyValueInternal(int record, object store, BitArray nullbits, int storeIndex) { 
            CopyValue(record, store, nullbits, storeIndex);

        internal void SetStorageInternal(object store, BitArray nullbits) {
            SetStorage(store, nullbits);

        abstract protected Object GetEmptyStorage(int recordCount); 
        abstract protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex); 
        abstract protected void SetStorage(object store, BitArray nullbits);
        protected void SetNullStorage(BitArray nullbits) { 
            dbNullBits = nullbits;

        /// wrapper around Type.GetType 
        /// assembly qualified type name or one of the special known types
        /// Type or null if not found 
        /// when type implements IDynamicMetaObjectProvider and not IXmlSerializable 
        /// Types like "System.Guid" will load regardless of AssemblyQualifiedName because they are special 
        /// Types like "System.Data.SqlTypes.SqlString" will load because they are in the same assembly as this code
        /// Types like "System.Numerics.BigInteger" won't load because they are not special and not same assembly as this code
        internal static Type GetType(string value) { 
            Type dataType = Type.GetType(value); // throwOnError=false, ignoreCase=fase
            if (null == dataType) { 
                if ("System.Numerics.BigInteger" == value) { 
                    dataType = typeof(System.Numerics.BigInteger);

            // Dev10 671061: prevent reading type from schema which implements IDynamicMetaObjectProvider and not IXmlSerializable
            // the check here prevents the type from being loaded in schema or as instance data (when DataType is object) 
            return dataType; 

        /// wrapper around Type.AssemblyQualifiedName 
        /// qualified name when writing in xml
        /// when type implements IDynamicMetaObjectProvider and not IXmlSerializable
        internal static string GetQualifiedName(Type type) 
            Debug.Assert(null != type, "null type"); 
            return type.AssemblyQualifiedName;

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK