Type converter for ODP.NET

Posts   
 
    
dhjepson
User
Posts: 5
Joined: 09-Oct-2012
# Posted on: 10-Oct-2012 17:29:57   

I am a relatively new user tasked with converting our data access from MS oracle to ODP.net. Under MS oracle all of our number(x,0) types imported as essentially Sytem.Decimal .net types. All of our entity extensions are built around this type. With ODP.net our number(x,0) types import as Int16/32/64 depending on size. Not wanting to change all our existing code, and after fishing around in the documentation, I saw how it was possible to write a custom type converter. I have tried to implement a converter that will convert the native Int16/32/64 types to System.Decimal using examples of other type converters I found on the forums. After compiling and running, the number of InvalidCastException errors clearly indicates I am in over my head. I think I may be confusing my ConvertFroms from my ConvertTos simple_smile Perhaps someone can tell me if I am even heading in the right direction. Here is my code for the decimal/Int16 converter. (Using 2.6 with the 09132012 run time libraries.)


public class DecimalInteger16Converter : TypeConverter
    {
        #region Method Overrides

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            // check if conversion is supported from the source type
            switch (sourceType.FullName)
            {
                case "System.Int16":
                case "System.Decimal":
                    return true;
                default:
                    return false;
            }
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            // check if conversion to the destination type is supported
            switch (destinationType.FullName)
            {
                case "System.Int16":
                case "System.Decimal":
                    return true;
                default:
                    return false;
            }
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            // convert from the source type to the destination type

            // make sure value isn't null
            if (value == null)
            {
                return null;
            }


            if (value.GetType().FullName == "System.Int16")
            {
                return Convert.ToInt16(value);
            }

            return value;
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            // make sure value isn't null
            if (value == null)
                throw new ArgumentNullException("value", "Value can't be null");

            
            // value is always a Decimal

            return Convert.ToDecimal(value);

            
        }

        public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
        {
            System.Decimal x = 0;
            return x;
        }

        #endregion
    }


I’m guessing that I don’t have something quite right in this converter. If someone can quickly see my problem (or point me to a converter that already does this), I might be able to continue on down the path. Thanks

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Oct-2012 04:19:50   

Your guess is right: you switched the ConvertFrom/ConvertTo methods. They should look like:

 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            // convert from the Int16 on DB (mapped by the driver) to my wanted Decimal

            // make sure value isn't null
            if (value == null)
            {
                return null;
            }

            if (value.GetType().FullName == "System.Int16")
            {
                return Convert.ToDecimal(value);
            }
            else
           {
                 throw new NotSupportedException("Conversion from a value of type '" + value.GetType().ToString() + "' to System.Decimal isn't supported");
           }
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            // make sure value isn't null
            if (value == null)
            {
                throw new ArgumentNullException("value", "Value can't be null");
             }


            
            // value is always a Decimal
            if (destinationType.FullName == "System.Int16" )
            {
                 return Convert.ToInt16(value);
             }
             else
            {
                    throw new NotSupportedException("Conversion to a value of type '" + destinationType.ToString() + "' isn't supported");
             }          
        }

BTW, you could write a typeConvert that converts Decimal From/To Int16/32/64 in the same converter (using switches).

David Elizondo | LLBLGen Support Team
dhjepson
User
Posts: 5
Joined: 09-Oct-2012
# Posted on: 11-Oct-2012 16:54:25   

Aah, yes. Thank you very much. That did the trick simple_smile