Este dilema se puede abordar de diversas formas, pero te enseñamos la respuesta más completa en nuestra opinión.
Solución:
Su enfoque es un buen comienzo, pero completar ese diccionario solo debe hacerse una vez, como dice Ian en un comentario.
Aquí hay un GIST que se basa en la misma idea, aunque no convierte entre los mismos conjuntos de tipos: https://gist.github.com/abrahamjp/858392
Advertencia
Tengo un ejemplo de trabajo a continuación, pero debe tener en cuenta que este enfoque tiene algunos problemas. Por ejemplo:
- Para
string
, ¿cómo eliges el correcto entreChar
,NChar
,VarChar
,NVarChar
,Text
oNText
(o inclusoXml
, quizás)? - Y para manchas como
byte[]
, deberías usarBinary
,VarBinary
oImage
? - Para
decimal
,float
ydouble
, deberías ir porDecimal
,Float
,Money
,SmallMoney
oReal
? - Para
DateTime
, necesitasDateTime2
,DateTimeOffset
,DateTime
, oSmallDateTime
? - Estas usando
Nullable
tipos, comoint?
? Esas probablemente deberían dar lo mismoSqlDbType
como el tipo subyacente.
Además, solo brindando un Type
no le dice nada sobre otras restricciones, como el tamaño y la precisión del campo. Tomar la decisión correcta también se trata de cómo se utilizan los datos en su aplicación y cómo se almacenan en la base de datos.
Lo mejor que puede hacer es dejar que un ORM lo haga por usted.
Código
public static class SqlHelper
private static Dictionary typeMap;
// Create and populate the dictionary in the static constructor
static SqlHelper()
typeMap = new Dictionary();
typeMap[typeof(string)] = SqlDbType.NVarChar;
typeMap[typeof(char[])] = SqlDbType.NVarChar;
typeMap[typeof(byte)] = SqlDbType.TinyInt;
typeMap[typeof(short)] = SqlDbType.SmallInt;
typeMap[typeof(int)] = SqlDbType.Int;
typeMap[typeof(long)] = SqlDbType.BigInt;
typeMap[typeof(byte[])] = SqlDbType.Image;
typeMap[typeof(bool)] = SqlDbType.Bit;
typeMap[typeof(DateTime)] = SqlDbType.DateTime2;
typeMap[typeof(DateTimeOffset)] = SqlDbType.DateTimeOffset;
typeMap[typeof(decimal)] = SqlDbType.Money;
typeMap[typeof(float)] = SqlDbType.Real;
typeMap[typeof(double)] = SqlDbType.Float;
typeMap[typeof(TimeSpan)] = SqlDbType.Time;
/* ... and so on ... */
// Non-generic argument-based method
public static SqlDbType GetDbType(Type giveType)
// Allow nullable types to be handled
giveType = Nullable.GetUnderlyingType(giveType) ?? giveType;
if (typeMap.ContainsKey(giveType))
return typeMap[giveType];
throw new ArgumentException($"giveType.FullName is not a supported .NET class");
// Generic version
public static SqlDbType GetDbType()
return GetDbType(typeof(T));
Y así es como lo usarías:
var sqlDbType = SqlHelper.GetDbType();
// or:
var sqlDbType = SqlHelper.GetDbType(typeof(DateTime?));
// or:
var sqlDbType = SqlHelper.GetDbType(property.PropertyType);
Parece que este tipo de tabla de búsqueda ya está disponible, aunque no en System.Data
(o .Object
o .Type
) sino en System.Web.
Proyecto -> Agregar referencia -> System.Web -> Aceptar
Entonces https://msdn.microsoft.com/en-us/library/system.data.sqldbtype(v=vs.110).aspx también dice
Al configurar los parámetros del comando, SqlDbType y DbType están vinculados. Por lo tanto, configurar DbType cambia SqlDbType a un SqlDbType compatible.
Entonces, esto debería funcionar teóricamente;)
using Microsoft.SqlServer.Server; // SqlDataRecord and SqlMetaData
using System;
using System.Collections; // IEnumerator and IEnumerable
using System.Collections.Generic; // general IEnumerable and IEnumerator
using System.Data; // DataTable and SqlDataType
using System.Data.SqlClient; // SqlConnection, SqlCommand, and SqlParameter
using System.Web.UI.WebControls; // for Parameters.Convert... functions
private static SqlDbType TypeToSqlDbType(Type t)
DbType dbtc = Parameters.ConvertTypeCodeToDbType(t.GetTypeCodeImpl());
SqlParameter sp = new SqlParameter();
// DbParameter dp = new DbParameter();
// dp.DbType = dbtc;
sp.DbType = dbtc;
return sp.SqlDbType;
Aquí puedes ver las reseñas y valoraciones de los usuarios
Si te animas, puedes dejar un escrito acerca de qué te ha parecido este enunciado.