Search code examples
ado.netsqlparametersqldbtype

How to know/check whether a value is SqlDbType compatible or not?


I'm assigning objects to this list of SqlParameter and then trying to execute the SqlCommand, but it throws an exception saying that one of the objects could not be converted into SqlDbType. Preferably I want to handle such objects before adding them to the parameter collection list. So, how would I check whether a value being added to parameter list is a good/proper one or not? What property should I check for?

Here's is my code :

bool Submit(Progs progs, CommandType commandType, string commandText)
{   
    try
    {
        List<SqlParameter> paramCollection = new List<SqlParameter>();
        foreach(Prog p in progs)
        {
            SqlParameter spTemp = new SqlParameter { ParameterName = p.Name , Value = p.Value};
            paramCollection.Add(spTemp);
            using (SqlConnection con = GetConnection())
            {
                SqlCommand cmd = new SqlCommand { CommandType = commandType, CommandText = commandText, Connection = con };  
                con.Open();
                cmd.Parameters.AddRange(paramCollection ); // Exception is thrown from this line
                cmd.ExecuteNonQuery();
            }
            return true;
        }
        catch(Exception exc)
        {
            return false;
        }
    }

The exception thown says : No mapping exists from object type sol2.CodeBase.BL.Letter[] to a known managed provider native type.

PS : There is a property for of SqlParameter called ParamaterIsSqlType(yes, it's paramAter and not paramEter), which appears only during runtime(i.e. when I inspect spTemp with a breakpoint on the next line) and which is always set to false? What kind of property is this, so that it appears only during runtime??? Also, what value this "ParamaterIsSqlType" indicates?


Solution

  • Do what SqlParameter would do to infer conversion from Type to SqlDbType if it's not set explicitely. So, no, there's (yet) no property or method available in the framework.

    System.Type type = p.Value.GetType();
    var isConvertible = IsConvertibleToSqlDbType(type);
    if(!isConvertible){
        //call your custom ToSqlType-method
    }
    

    Following method is derived directly from SqlParemeter's private void InferSqlType (object value):

    public static bool IsConvertibleToSqlDbType(Type type)
    {
        switch(type.FullName) {
            case "System.Int64":
            case "System.Data.SqlTypes.SqlInt64":
                //SetSqlDbType (SqlDbType.BigInt);
                return true;
            case "System.Boolean":
            case "System.Data.SqlTypes.SqlBoolean":
                //SetSqlDbType (SqlDbType.Bit);
                return true;
            case "System.String":
            case "System.Data.SqlTypes.SqlString":
                //SetSqlDbType (SqlDbType.NVarChar);
                return true;
            case "System.DateTime":
            case "System.Data.SqlTypes.SqlDateTime":
                //SetSqlDbType (SqlDbType.DateTime);
                return true;
            case "System.Decimal":
            case "System.Data.SqlTypes.SqlDecimal":
                //SetSqlDbType (SqlDbType.Decimal);
                return true;
            case "System.Double":
            case "System.Data.SqlTypes.SqlDouble":
                //SetSqlDbType (SqlDbType.Float);
                return true;
            case "System.Byte[]":
            case "System.Data.SqlTypes.SqlBinary":
                //SetSqlDbType (SqlDbType.VarBinary);
                return true;
            case "System.Byte":
            case "System.Data.SqlTypes.SqlByte":
                //SetSqlDbType (SqlDbType.TinyInt);
                return true;
            case "System.Int32":
            case "System.Data.SqlTypes.SqlInt32":
                //SetSqlDbType (SqlDbType.Int);
                return true;
            case "System.Single":
            case "System.Data.SqlTypes.Single":
                //SetSqlDbType (SqlDbType.Real);
                return true;
            case "System.Int16":
            case "System.Data.SqlTypes.SqlInt16":
                //SetSqlDbType (SqlDbType.SmallInt);
                return true;
            case "System.Guid":
            case "System.Data.SqlTypes.SqlGuid":
                //SetSqlDbType (SqlDbType.UniqueIdentifier);
                return true;
            case "System.Money":
            case "System.SmallMoney":
            case "System.Data.SqlTypes.SqlMoney":
                //SetSqlDbType (SqlDbType.Money);
                return true;
            case "System.Object":
                //SetSqlDbType (SqlDbType.Variant); 
                return true;
            default:
                return false;
        }
    }