Mercurial > pub > bltoolkit
view Source/Data/Sql/SqlDataType.cs @ 9:1e85f66cf767 default tip
update bltoolkit
author | nickolay |
---|---|
date | Thu, 05 Apr 2018 20:53:26 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlTypes; using System.Linq; using System.Text; namespace BLToolkit.Data.Sql { using Reflection; public class SqlDataType : ISqlExpression { #region Init public SqlDataType(SqlDbType dbType) { var defaultType = GetDataType(dbType); SqlDbType = dbType; Type = defaultType.Type; Length = defaultType.Length; Precision = defaultType.Precision; Scale = defaultType.Scale; } public SqlDataType(SqlDbType dbType, int length) { if (length <= 0) throw new ArgumentOutOfRangeException("length"); SqlDbType = dbType; Type = GetDataType(dbType).Type; Length = length; } public SqlDataType(SqlDbType dbType, int precision, int scale) { if (precision <= 0) throw new ArgumentOutOfRangeException("precision"); if (scale < 0) throw new ArgumentOutOfRangeException("scale"); SqlDbType = dbType; Type = GetDataType(dbType).Type; Precision = precision; Scale = scale; } public SqlDataType([JetBrains.Annotations.NotNull]Type type) { if (type == null) throw new ArgumentNullException("type"); var defaultType = GetDataType(type); SqlDbType = defaultType.SqlDbType; Type = type; Length = defaultType.Length; Precision = defaultType.Precision; Scale = defaultType.Scale; } public SqlDataType([JetBrains.Annotations.NotNull] Type type, int length) { if (type == null) throw new ArgumentNullException ("type"); if (length <= 0) throw new ArgumentOutOfRangeException("length"); SqlDbType = GetDataType(type).SqlDbType; Type = type; Length = length; } public SqlDataType([JetBrains.Annotations.NotNull] Type type, int precision, int scale) { if (type == null) throw new ArgumentNullException ("type"); if (precision <= 0) throw new ArgumentOutOfRangeException("precision"); if (scale < 0) throw new ArgumentOutOfRangeException("scale"); SqlDbType = GetDataType(type).SqlDbType; Type = type; Precision = precision; Scale = scale; } public SqlDataType(SqlDbType dbType, [JetBrains.Annotations.NotNull]Type type) { if (type == null) throw new ArgumentNullException("type"); var defaultType = GetDataType(dbType); SqlDbType = dbType; Type = type; Length = defaultType.Length; Precision = defaultType.Precision; Scale = defaultType.Scale; } public SqlDataType(SqlDbType dbType, [JetBrains.Annotations.NotNull] Type type, int length) { if (type == null) throw new ArgumentNullException ("type"); if (length <= 0) throw new ArgumentOutOfRangeException("length"); SqlDbType = dbType; Type = type; Length = length; } public SqlDataType(SqlDbType dbType, [JetBrains.Annotations.NotNull] Type type, int precision, int scale) { if (type == null) throw new ArgumentNullException ("type"); if (precision <= 0) throw new ArgumentOutOfRangeException("precision"); if (scale < 0) throw new ArgumentOutOfRangeException("scale"); SqlDbType = dbType; Type = type; Precision = precision; Scale = scale; } #endregion #region Public Members public SqlDbType SqlDbType { get; private set; } public Type Type { get; private set; } public int Length { get; private set; } public int Precision { get; private set; } public int Scale { get; private set; } #endregion #region Static Members struct TypeInfo { public TypeInfo(SqlDbType dbType, int maxLength, int maxPrecision, int maxScale, int maxDisplaySize) { SqlDbType = dbType; MaxLength = maxLength; MaxPrecision = maxPrecision; MaxScale = maxScale; MaxDisplaySize = maxDisplaySize; } public readonly SqlDbType SqlDbType; public readonly int MaxLength; public readonly int MaxPrecision; public readonly int MaxScale; public readonly int MaxDisplaySize; } static TypeInfo[] SortTypeInfo(params TypeInfo[] info) { var sortedInfo = new TypeInfo[info.Max(ti => (int)ti.SqlDbType) + 1]; foreach (var typeInfo in info) sortedInfo[(int)typeInfo.SqlDbType] = typeInfo; return sortedInfo; } static int Len(object obj) { return obj.ToString().Length; } static readonly TypeInfo[] _typeInfo = SortTypeInfo ( // DbType MaxLength MaxPrecision MaxScale MaxDisplaySize // new TypeInfo(SqlDbType.BigInt, 8, Len( long.MaxValue), 0, Len( long.MinValue)), new TypeInfo(SqlDbType.Int, 4, Len( int.MaxValue), 0, Len( int.MinValue)), new TypeInfo(SqlDbType.SmallInt, 2, Len(short.MaxValue), 0, Len(short.MinValue)), new TypeInfo(SqlDbType.TinyInt, 1, Len( byte.MaxValue), 0, Len( byte.MaxValue)), new TypeInfo(SqlDbType.Bit, 1, 1, 0, 1), new TypeInfo(SqlDbType.Decimal, 17, Len(decimal.MaxValue), Len(decimal.MaxValue), Len(decimal.MinValue)+1), new TypeInfo(SqlDbType.Money, 8, 19, 4, 19 + 2), new TypeInfo(SqlDbType.SmallMoney, 4, 10, 4, 10 + 2), new TypeInfo(SqlDbType.Float, 8, 15, 15, 15 + 2 + 5), new TypeInfo(SqlDbType.Real, 4, 7, 7, 7 + 2 + 4), new TypeInfo(SqlDbType.DateTime, 8, -1, -1, 23), #if !MONO new TypeInfo(SqlDbType.DateTime2, 8, -1, -1, 27), #endif new TypeInfo(SqlDbType.SmallDateTime, 4, -1, -1, 19), new TypeInfo(SqlDbType.Date, 3, -1, -1, 10), new TypeInfo(SqlDbType.Time, 5, -1, -1, 16), #if !MONO new TypeInfo(SqlDbType.DateTimeOffset, 10, -1, -1, 34), #endif new TypeInfo(SqlDbType.Char, 8000, -1, -1, 8000), new TypeInfo(SqlDbType.VarChar, 8000, -1, -1, 8000), new TypeInfo(SqlDbType.Text, int.MaxValue, -1, -1, int.MaxValue), new TypeInfo(SqlDbType.NChar, 4000, -1, -1, 4000), new TypeInfo(SqlDbType.NVarChar, 4000, -1, -1, 4000), new TypeInfo(SqlDbType.NText, int.MaxValue, -1, -1, int.MaxValue / 2), new TypeInfo(SqlDbType.Binary, 8000, -1, -1, -1), new TypeInfo(SqlDbType.VarBinary, 8000, -1, -1, -1), new TypeInfo(SqlDbType.Image, int.MaxValue, -1, -1, -1), new TypeInfo(SqlDbType.Timestamp, 8, -1, -1, -1), new TypeInfo(SqlDbType.UniqueIdentifier, 16, -1, -1, 36), new TypeInfo(SqlDbType.Variant, -1, -1, -1, -1), new TypeInfo(SqlDbType.Xml, -1, -1, -1, -1), #if !MONO new TypeInfo(SqlDbType.Structured, -1, -1, -1, -1), #endif new TypeInfo(SqlDbType.Udt, -1, -1, -1, -1) ); public static int GetMaxLength (SqlDbType dbType) { return _typeInfo[(int)dbType].MaxLength; } public static int GetMaxPrecision (SqlDbType dbType) { return _typeInfo[(int)dbType].MaxPrecision; } public static int GetMaxScale (SqlDbType dbType) { return _typeInfo[(int)dbType].MaxScale; } public static int GetMaxDisplaySize(SqlDbType dbType) { return _typeInfo[(int)dbType].MaxDisplaySize; } public static SqlDataType GetDataType(Type type) { var underlyingType = type; if (underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition() == typeof(Nullable<>)) underlyingType = underlyingType.GetGenericArguments()[0]; if (underlyingType.IsEnum) underlyingType = Enum.GetUnderlyingType(underlyingType); switch (Type.GetTypeCode(underlyingType)) { case TypeCode.Boolean : return Boolean; case TypeCode.Char : return Char; case TypeCode.SByte : return SByte; case TypeCode.Byte : return Byte; case TypeCode.Int16 : return Int16; case TypeCode.UInt16 : return UInt16; case TypeCode.Int32 : return Int32; case TypeCode.UInt32 : return UInt32; case TypeCode.Int64 : return Int64; case TypeCode.UInt64 : return UInt64; case TypeCode.Single : return Single; case TypeCode.Double : return Double; case TypeCode.Decimal : return Decimal; case TypeCode.DateTime : return DateTime; case TypeCode.String : return String; case TypeCode.Object : if (underlyingType == typeof(Guid)) return Guid; if (underlyingType == typeof(byte[])) return ByteArray; if (underlyingType == typeof(System.Data.Linq.Binary)) return LinqBinary; if (underlyingType == typeof(char[])) return CharArray; #if !MONO if (underlyingType == typeof(DateTimeOffset)) return DateTimeOffset; #endif if (underlyingType == typeof(TimeSpan)) return TimeSpan; break; case TypeCode.DBNull : case TypeCode.Empty : default : break; } #if !SILVERLIGHT if (underlyingType == typeof(SqlByte)) return SqlByte; if (underlyingType == typeof(SqlInt16)) return SqlInt16; if (underlyingType == typeof(SqlInt32)) return SqlInt32; if (underlyingType == typeof(SqlInt64)) return SqlInt64; if (underlyingType == typeof(SqlSingle)) return SqlSingle; if (underlyingType == typeof(SqlBoolean)) return SqlBoolean; if (underlyingType == typeof(SqlDouble)) return SqlDouble; if (underlyingType == typeof(SqlDateTime)) return SqlDateTime; if (underlyingType == typeof(SqlDecimal)) return SqlDecimal; if (underlyingType == typeof(SqlMoney)) return SqlMoney; if (underlyingType == typeof(SqlString)) return SqlString; if (underlyingType == typeof(SqlBinary)) return SqlBinary; if (underlyingType == typeof(SqlGuid)) return SqlGuid; if (underlyingType == typeof(SqlBytes)) return SqlBytes; if (underlyingType == typeof(SqlChars)) return SqlChars; if (underlyingType == typeof(SqlXml)) return SqlXml; #endif return DbVariant; } public static SqlDataType GetDataType(SqlDbType type) { switch (type) { case SqlDbType.BigInt : return DbBigInt; case SqlDbType.Binary : return DbBinary; case SqlDbType.Bit : return DbBit; case SqlDbType.Char : return DbChar; case SqlDbType.DateTime : return DbDateTime; case SqlDbType.Decimal : return DbDecimal; case SqlDbType.Float : return DbFloat; case SqlDbType.Image : return DbImage; case SqlDbType.Int : return DbInt; case SqlDbType.Money : return DbMoney; case SqlDbType.NChar : return DbNChar; case SqlDbType.NText : return DbNText; case SqlDbType.NVarChar : return DbNVarChar; case SqlDbType.Real : return DbReal; case SqlDbType.UniqueIdentifier : return DbUniqueIdentifier; case SqlDbType.SmallDateTime : return DbSmallDateTime; case SqlDbType.SmallInt : return DbSmallInt; case SqlDbType.SmallMoney : return DbSmallMoney; case SqlDbType.Text : return DbText; case SqlDbType.Timestamp : return DbTimestamp; case SqlDbType.TinyInt : return DbTinyInt; case SqlDbType.VarBinary : return DbVarBinary; case SqlDbType.VarChar : return DbVarChar; case SqlDbType.Variant : return DbVariant; #if !SILVERLIGHT case SqlDbType.Xml : return DbXml; #endif case SqlDbType.Udt : return DbUdt; #if !MONO case SqlDbType.Structured : return DbStructured; #endif case SqlDbType.Date : return DbDate; case SqlDbType.Time : return DbTime; #if !MONO case SqlDbType.DateTime2 : return DbDateTime2; case SqlDbType.DateTimeOffset : return DbDateTimeOffset; #endif } throw new InvalidOperationException(); } public static bool CanBeNull(Type type) { if (type.IsValueType == false || type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) || TypeHelper.IsSameOrParent(typeof(INullable), type)) return true; return false; } #endregion #region Default Types internal SqlDataType(SqlDbType dbType, Type type, int length, int precision, int scale) { SqlDbType = dbType; Type = type; Length = length; Precision = precision; Scale = scale; } SqlDataType(SqlDbType dbType, Type type, Func<SqlDbType,int> length, int precision, int scale) : this(dbType, type, length(dbType), precision, scale) { } SqlDataType(SqlDbType dbType, Type type, int length, Func<SqlDbType,int> precision, int scale) : this(dbType, type, length, precision(dbType), scale) { } public static readonly SqlDataType DbBigInt = new SqlDataType(SqlDbType.BigInt, typeof(Int64), 0, 0, 0); public static readonly SqlDataType DbInt = new SqlDataType(SqlDbType.Int, typeof(Int32), 0, 0, 0); public static readonly SqlDataType DbSmallInt = new SqlDataType(SqlDbType.SmallInt, typeof(Int16), 0, 0, 0); public static readonly SqlDataType DbTinyInt = new SqlDataType(SqlDbType.TinyInt, typeof(Byte), 0, 0, 0); public static readonly SqlDataType DbBit = new SqlDataType(SqlDbType.Bit, typeof(Boolean), 0, 0, 0); public static readonly SqlDataType DbDecimal = new SqlDataType(SqlDbType.Decimal, typeof(Decimal), 0, GetMaxPrecision, 10); public static readonly SqlDataType DbMoney = new SqlDataType(SqlDbType.Money, typeof(Decimal), 0, GetMaxPrecision, 4); public static readonly SqlDataType DbSmallMoney = new SqlDataType(SqlDbType.SmallMoney, typeof(Decimal), 0, GetMaxPrecision, 4); public static readonly SqlDataType DbFloat = new SqlDataType(SqlDbType.Float, typeof(Double), 0, 0, 0); public static readonly SqlDataType DbReal = new SqlDataType(SqlDbType.Real, typeof(Single), 0, 0, 0); public static readonly SqlDataType DbDateTime = new SqlDataType(SqlDbType.DateTime, typeof(DateTime), 0, 0, 0); #if !MONO public static readonly SqlDataType DbDateTime2 = new SqlDataType(SqlDbType.DateTime2, typeof(DateTime), 0, 0, 0); #else public static readonly SqlDataType DbDateTime2 = new SqlDataType(SqlDbType.DateTime, typeof(DateTime), 0, 0, 0); #endif public static readonly SqlDataType DbSmallDateTime = new SqlDataType(SqlDbType.SmallDateTime, typeof(DateTime), 0, 0, 0); public static readonly SqlDataType DbDate = new SqlDataType(SqlDbType.Date, typeof(DateTime), 0, 0, 0); public static readonly SqlDataType DbTime = new SqlDataType(SqlDbType.Time, typeof(TimeSpan), 0, 0, 0); #if !MONO public static readonly SqlDataType DbDateTimeOffset = new SqlDataType(SqlDbType.DateTimeOffset, typeof(DateTimeOffset), 0, 0, 0); #endif public static readonly SqlDataType DbChar = new SqlDataType(SqlDbType.Char, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbVarChar = new SqlDataType(SqlDbType.VarChar, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbText = new SqlDataType(SqlDbType.Text, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbNChar = new SqlDataType(SqlDbType.NChar, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbNVarChar = new SqlDataType(SqlDbType.NVarChar, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbNText = new SqlDataType(SqlDbType.NText, typeof(String), GetMaxLength, 0, 0); public static readonly SqlDataType DbBinary = new SqlDataType(SqlDbType.Binary, typeof(Byte[]), GetMaxLength, 0, 0); public static readonly SqlDataType DbVarBinary = new SqlDataType(SqlDbType.VarBinary, typeof(Byte[]), GetMaxLength, 0, 0); public static readonly SqlDataType DbImage = new SqlDataType(SqlDbType.Image, typeof(Byte[]), GetMaxLength, 0, 0); public static readonly SqlDataType DbTimestamp = new SqlDataType(SqlDbType.Timestamp, typeof(Byte[]), 0, 0, 0); public static readonly SqlDataType DbUniqueIdentifier = new SqlDataType(SqlDbType.UniqueIdentifier, typeof(Guid), 0, 0, 0); public static readonly SqlDataType DbVariant = new SqlDataType(SqlDbType.Variant, typeof(Object), 0, 0, 0); #if !SILVERLIGHT public static readonly SqlDataType DbXml = new SqlDataType(SqlDbType.Xml, typeof(SqlXml), 0, 0, 0); #endif public static readonly SqlDataType DbUdt = new SqlDataType(SqlDbType.Udt, typeof(Object), 0, 0, 0); #if !MONO public static readonly SqlDataType DbStructured = new SqlDataType(SqlDbType.Structured, typeof(Object), 0, 0, 0); #endif public static readonly SqlDataType Boolean = DbBit; public static readonly SqlDataType Char = new SqlDataType(SqlDbType.Char, typeof(Char), 1, 0, 0); public static readonly SqlDataType SByte = new SqlDataType(SqlDbType.SmallInt, typeof(SByte), 0, 0, 0); public static readonly SqlDataType Byte = DbTinyInt; public static readonly SqlDataType Int16 = DbSmallInt; public static readonly SqlDataType UInt16 = new SqlDataType(SqlDbType.Int, typeof(UInt16), 0, 0, 0); public static readonly SqlDataType Int32 = DbInt; public static readonly SqlDataType UInt32 = new SqlDataType(SqlDbType.BigInt, typeof(UInt32), 0, 0, 0); public static readonly SqlDataType Int64 = DbBigInt; public static readonly SqlDataType UInt64 = new SqlDataType(SqlDbType.Decimal, typeof(UInt64), 0, ulong.MaxValue.ToString().Length, 0); public static readonly SqlDataType Single = DbReal; public static readonly SqlDataType Double = DbFloat; public static readonly SqlDataType Decimal = DbDecimal; public static readonly SqlDataType DateTime = DbDateTime2; public static readonly SqlDataType String = DbNVarChar; public static readonly SqlDataType Guid = DbUniqueIdentifier; public static readonly SqlDataType ByteArray = DbVarBinary; public static readonly SqlDataType LinqBinary = DbVarBinary; public static readonly SqlDataType CharArray = new SqlDataType(SqlDbType.NVarChar, typeof(Char[]), GetMaxLength, 0, 0); #if !MONO public static readonly SqlDataType DateTimeOffset = DbDateTimeOffset; #endif public static readonly SqlDataType TimeSpan = DbTime; #if !SILVERLIGHT public static readonly SqlDataType SqlByte = new SqlDataType(SqlDbType.TinyInt, typeof(SqlByte), 0, 0, 0); public static readonly SqlDataType SqlInt16 = new SqlDataType(SqlDbType.SmallInt, typeof(SqlInt16), 0, 0, 0); public static readonly SqlDataType SqlInt32 = new SqlDataType(SqlDbType.Int, typeof(SqlInt32), 0, 0, 0); public static readonly SqlDataType SqlInt64 = new SqlDataType(SqlDbType.BigInt, typeof(SqlInt64), 0, 0, 0); public static readonly SqlDataType SqlSingle = new SqlDataType(SqlDbType.Real, typeof(SqlSingle), 0, 0, 0); public static readonly SqlDataType SqlBoolean = new SqlDataType(SqlDbType.Bit, typeof(SqlBoolean), 0, 0, 0); public static readonly SqlDataType SqlDouble = new SqlDataType(SqlDbType.Float, typeof(SqlDouble), 0, 0, 0); public static readonly SqlDataType SqlDateTime = new SqlDataType(SqlDbType.DateTime, typeof(SqlDateTime), 0, 0, 0); public static readonly SqlDataType SqlDecimal = new SqlDataType(SqlDbType.Decimal, typeof(SqlDecimal), 0, GetMaxPrecision, 10); public static readonly SqlDataType SqlMoney = new SqlDataType(SqlDbType.Money, typeof(SqlMoney), 0, GetMaxPrecision, 4); public static readonly SqlDataType SqlString = new SqlDataType(SqlDbType.NVarChar, typeof(SqlString), GetMaxLength, 0, 0); public static readonly SqlDataType SqlBinary = new SqlDataType(SqlDbType.Binary, typeof(SqlBinary), GetMaxLength, 0, 0); public static readonly SqlDataType SqlGuid = new SqlDataType(SqlDbType.UniqueIdentifier, typeof(SqlGuid), 0, 0, 0); public static readonly SqlDataType SqlBytes = new SqlDataType(SqlDbType.Image, typeof(SqlBytes), GetMaxLength, 0, 0); public static readonly SqlDataType SqlChars = new SqlDataType(SqlDbType.Text, typeof(SqlChars), GetMaxLength, 0, 0); public static readonly SqlDataType SqlXml = new SqlDataType(SqlDbType.Xml, typeof(SqlXml), 0, 0, 0); #endif #endregion #region Overrides #if OVERRIDETOSTRING public override string ToString() { return ((IQueryElement)this).ToString(new StringBuilder(), new Dictionary<IQueryElement,IQueryElement>()).ToString(); } #endif #endregion #region ISqlExpression Members public int Precedence { get { return Sql.Precedence.Primary; } } public Type SystemType { get { return typeof(Type); } } #endregion #region ISqlExpressionWalkable Members ISqlExpression ISqlExpressionWalkable.Walk(bool skipColumns, Func<ISqlExpression,ISqlExpression> func) { return func(this); } #endregion #region IEquatable<ISqlExpression> Members bool IEquatable<ISqlExpression>.Equals(ISqlExpression other) { if (this == other) return true; var value = (SqlDataType)other; return Type == value.Type && Length == value.Length && Precision == value.Precision && Scale == value.Scale; } #endregion #region ISqlExpression Members public bool CanBeNull() { return false; } public bool Equals(ISqlExpression other, Func<ISqlExpression,ISqlExpression,bool> comparer) { return ((ISqlExpression)this).Equals(other) && comparer(this, other); } #endregion #region ICloneableElement Members public ICloneableElement Clone(Dictionary<ICloneableElement, ICloneableElement> objectTree, Predicate<ICloneableElement> doClone) { if (!doClone(this)) return this; ICloneableElement clone; if (!objectTree.TryGetValue(this, out clone)) objectTree.Add(this, clone = new SqlDataType(SqlDbType, Type, Length, Precision, Scale)); return clone; } #endregion #region IQueryElement Members public QueryElementType ElementType { get { return QueryElementType.SqlDataType; } } StringBuilder IQueryElement.ToString(StringBuilder sb, Dictionary<IQueryElement,IQueryElement> dic) { sb.Append(SqlDbType); if (Length != 0) sb.Append('(').Append(Length).Append(')'); else if (Precision != 0) sb.Append('(').Append(Precision).Append(',').Append(Scale).Append(')'); return sb; } #endregion } }