ADO.NET使用泛型将Decimal(4,2)转换为double

时间:2014-04-30 18:48:27

标签: c# sql sql-server sql-server-2008 ado.net

我正在尝试使用将字段转换为泛型类型的自定义方法将存储在SQL Server数据库中的十进制(4,2)字段转换为C#double。 (Method是SqlDataReader类的扩展。)

当我运行代码时,我不断收到错误“指定的强制转换无效”。

以下是方法:

public static T Get<T>(this SqlDataReader reader, string field) 
{
    try {
        int index = reader.GetOrdinal(field);
        if (reader.IsDBNull(index)) return default(T);

        T item = (T)reader[index];
        return item;
    } catch (Exception e) {
        Console.WriteLine(e); 
        return default(T); 
    }
}

在我调用方法的地方,我正在将值读入类构造函数中,如:

// reader is a SqlDataReader instance with an open connection, and fields obtained via the 'Read()' method.
MyClass myObject = new MyClass(reader.Get<double>("My_Field"));

SqlDataReader中包含正确的数据。 index变量设置为正确的字段序号,在调试时我可以运行行reader[1];并获得正确的返回值,如:06.1

数据库失败的一些值是:0.001.006.1

我想找出造成这个问题的原因,并在通用方法(迄今为止适用于所有其他常见数据类型)中修复它,因为它旨在简化ADO并使其更易于阅读,而不是常规的上帝可怕的“锅炉板”ADO。

2 个答案:

答案 0 :(得分:2)

您无法将盒装小数转换为double;你必须先将其转换为未装箱的小数。您可以使用Convert类来执行您尝试执行的操作:

public static T Get<T>(this SqlDataReader reader, string field) 
{
    try {
        int index = reader.GetOrdinal(field);
        if (reader.IsDBNull(index)) return default(T);

        object item = reader[index];
        return item is T ? (T)item : (T)Convert.ChangeType(item, typeof(T));
    } catch (Exception e) {
        Console.WriteLine(e); 
        return default(T); 
    }
}

我确定在某些情况下这无法处理,但它应该足以让你开始。

答案 1 :(得分:1)

问题在于你是否进行了双重拼接(我可能没有在这里使用正确的术语)。

reader[index]会返回object,而double无法直接投放到decimal。必须先将其转换为decimal dec = 1.0M; object obj = dec; var x = (double)dec; //succeeds var y = (double)obj; //fails

(double)reader.Get<decimal>("My_Field"))

我不确定是否有解决此问题的方法,除了使用通用函数获取存储在表中的值的实际类型,然后转换为要存储的变量的类型进入。

{{1}}