Domanda

I'm trying to convert a decimal(4,2) field stored in a SQL Server database to a C# double using a custom method which converts a field to a generic type. (Method is an extension of the SqlDataReader class.)

When I run the code, I keep getting the error "specified cast is not valid".

Here's the method:

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); 
    }
}

Where I'm calling the method, I'm reading the value right into a class constructor, like:

// 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"));

The SqlDataReader has the correct data in it. The index variable is set to the proper field ordinal which, and when in debug I can run the line reader[1]; and get a proper return value like: 0 or 6.1.

Some of the values from the database this has failed against are: 0.00, 1.00,6.1.

I'd like to figure out what is causing this problem and fix it within the generic method (which has worked for all other common data types so far), as it was designed to streamline ADO and make it easier to read, instead of the regular god-awful "boiler plate" ADO.

È stato utile?

Soluzione

You can't convert a boxed decimal to a double; you have to cast it to an unboxed decimal first. You can use the Convert class to do what you're trying to do:

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); 
    }
}

I'm sure there are some cases this doesn't handle, but it should be enough to get you started.

Altri suggerimenti

The problem is that you're double casting (I might not be using the right term here).

reader[index] returns an object which can't be cast to double directly. It must be cast to a decimal first.

decimal dec = 1.0M;
object obj = dec;

var x = (double)dec; //succeeds
var y = (double)obj; //fails

I'm not sure if there's a way around this issue other than using your generic function to get the actual type of the value stored on the table, then casting to type of the variable you want to store it into.

(double)reader.Get<decimal>("My_Field"))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top