diff Source/Data/Sql/SqlDataType.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Data/Sql/SqlDataType.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,555 @@
+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
+	}
+}