using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; namespace ZeroLevel.SqlServer { public static class DbTypeMapper { static Dictionary typeMap; static DbTypeMapper() { typeMap = new Dictionary { [typeof(byte)] = DbType.Byte, [typeof(sbyte)] = DbType.SByte, [typeof(short)] = DbType.Int16, [typeof(ushort)] = DbType.UInt16, [typeof(int)] = DbType.Int32, [typeof(uint)] = DbType.UInt32, [typeof(long)] = DbType.Int64, [typeof(ulong)] = DbType.UInt64, [typeof(float)] = DbType.Single, [typeof(double)] = DbType.Double, [typeof(decimal)] = DbType.Decimal, [typeof(bool)] = DbType.Boolean, [typeof(string)] = DbType.String, [typeof(char)] = DbType.StringFixedLength, [typeof(Guid)] = DbType.Guid, [typeof(DateTime)] = DbType.DateTime, [typeof(DateTimeOffset)] = DbType.DateTimeOffset, [typeof(TimeSpan)] = DbType.Time, [typeof(byte[])] = DbType.Binary, [typeof(byte?)] = DbType.Byte, [typeof(sbyte?)] = DbType.SByte, [typeof(short?)] = DbType.Int16, [typeof(ushort?)] = DbType.UInt16, [typeof(int?)] = DbType.Int32, [typeof(uint?)] = DbType.UInt32, [typeof(long?)] = DbType.Int64, [typeof(ulong?)] = DbType.UInt64, [typeof(float?)] = DbType.Single, [typeof(double?)] = DbType.Double, [typeof(decimal?)] = DbType.Decimal, [typeof(bool?)] = DbType.Boolean, [typeof(char?)] = DbType.StringFixedLength, [typeof(Guid?)] = DbType.Guid, [typeof(DateTime?)] = DbType.DateTime, [typeof(DateTimeOffset?)] = DbType.DateTimeOffset, [typeof(TimeSpan?)] = DbType.Time, [typeof(object)] = DbType.Object }; } /// /// Для value типов помеченных как Nullable вытаскивает оригинальный value тип /// Не value и не nullable типы не преобразуются /// private static Type GetNonNullableType(Type t) { if (t.IsValueType) { // Detect Nullable if (Nullable.GetUnderlyingType(t) != null) { return t.GenericTypeArguments.Length > 0 ? t.GenericTypeArguments[0] : t; } } return t; } public static DbType ToDbType(this Type type) { DbType dbType; var theType = GetNonNullableType(type); if (theType.IsEnum && !typeMap.ContainsKey(type)) { theType = Enum.GetUnderlyingType(theType); } if (typeMap.TryGetValue(theType, out dbType)) { return dbType; } return DbType.Object; } public static SqlDbType ToSqlDbType(this Type testType) { var theType = GetNonNullableType(testType); if (theType.IsEnum) { return Enum.GetUnderlyingType(theType).ToSqlDbType(); } if (theType == typeof(Byte[]) || theType == typeof(byte[])) return SqlDbType.Image; if (theType == typeof(UInt16) || theType == typeof(ushort)) return SqlDbType.Int; if (theType == typeof(UInt32) || theType == typeof(uint)) return SqlDbType.BigInt; if (theType == typeof(UInt64) || theType == typeof(ulong)) return SqlDbType.Decimal; if (theType == typeof(TimeSpan)) return SqlDbType.Time; return new SqlParameter() { DbType = (DbType)Enum.Parse(typeof(DbType), theType.Name) }.SqlDbType; } public static Type ToClrType(string sqlType) { switch (sqlType.Trim().ToLowerInvariant()) { case "bigint": return typeof(long); case "binary": case "image": case "timestamp": case "varbinary": return typeof(byte[]); case "bit": return typeof(bool); case "char": case "nchar": case "ntext": case "nvarchar": case "text": case "varchar": case "xml": return typeof(string); case "datetime": case "smalldatetime": case "date": case "datetime2": return typeof(DateTime); case "time": return typeof(TimeSpan); case "decimal": case "money": case "smallmoney": return typeof(decimal); case "float": return typeof(double); case "int": return typeof(int); case "real": return typeof(float); case "uniqueidentifier": return typeof(Guid); case "smallint": return typeof(short); case "tinyint": return typeof(byte); case "variant": case "udt": return typeof(object); case "structured": return typeof(DataTable); case "datetimeoffset": return typeof(DateTimeOffset); default: throw new ArgumentOutOfRangeException(sqlType); } } } }