How to add a new type Converter to LLBLGen

Posts   
 
    
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 14-Sep-2006 17:24:01   

I created a class library in C#.net for Type converter to convert Number(oracle) to int(c#). I used the example from this thread to do this. http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7355&HighLight=1

I place the output dll which I got in C:\Program Files\Solutions Design\LLBLGen Pro\TypeConverters directory. Now when I open LLBLGen to create datatier, I am not getting my namespace in the Type Conversion Editor. My question is how do I get my namespace in this editor? Here is the code I wrote to do this.

using System;
//using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Oracle.DataAccess.Client;
namespace DBType2NETType.TypeConverters
{

    public class NumberToInt32 : TypeConverter
    {
        public NumberToInt32 ()
        {
        }

        public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
        {
            switch ( sourceType.FullName )
            {
                case "OracleDbType.Int64":
                    return true;
                default:
                    return false;
            }
        }

        public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
        {
            switch ( destinationType.FullName )
            {
                case "System.Int32":
                    return true;
                default:
                    return false;
            }
        }

        public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value )
        {
            //YourNamespace.YourEnumType yourEnum = YourNamespace.YourEnumType.ADefaultValue;
                    
            int returnValue = 0;
            switch ( value.GetType().FullName )
            {
                case "OracleDbType.Int64":
                    //yourEnum = (YourNamespace.YourEnumType)Enum.ToObject( typeof( YourNamespace.YourEnumType), (int)value );
                    returnValue = Convert.ToInt32(value);
                    break;
                default:
                    throw new NotSupportedException( "Conversion from a value of type '" + value.GetType().ToString() + "' to System.Int32 isn't supported" );
            }

            return returnValue;
        }

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

            if ( !( value is Int32) )
            {
                throw new ArgumentException( "Value isn't of type Int32", "value" );
            }

            int requiredValue = Convert.ToInt32(value);

            switch ( destinationType.FullName )
            {
                case "System.Int32":
                    return requiredValue;
                default:
                    throw new NotSupportedException( "Conversion to a value of type '" + destinationType.ToString() + "' isn't supported" );
            }
        }


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

    }
}

Any corrections and suggestions would be most welcome.

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 15-Sep-2006 08:40:06   

You specified that your type converter can convert from the following type "OracleDbType.Int64"

So my question is, when you select a field having type of "OracleDbType.Int64", do you see your type converter in the list?

Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 15-Sep-2006 08:50:17   

I need LLBLGEN to convert Number(11) in Oracle to Int32 of C#. Since I thought LLBLGEN will consider Number(11) as OracleDBType.Int64.

If you give me sample code to achieve this , so that I can add it to LLBLGEN, I would be so much thankful to you. Please guide me also how to add this type converter to LLBLGEN.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 15-Sep-2006 09:42:26   

If you're using llblgen pro v1.0.2005.1, you've to build your typeconverter with .NET 1.1 to make it show up in the designer, did you do that?

Frans Bouma | Lead developer LLBLGen Pro
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 15-Sep-2006 10:41:01   

Yes I created a class library project using dotnet version 1.1 and copied the output assembly to C:\Program Files\Solutions Design\LLBLGen Pro\TypeConverters. The name of the assembly is DBType2NETType.TypeConverters.dll. I placed this along with the one which is already there.SD.LLBLGen.Pro.TypeConverters.dll.

Then I opened LLBLGEN GUI and clicked edit type conversion menu. I am still seeing the converter which comes with the tool(boolean converter). Will I get my class as a new item in the combo box? Your ideas will help me a great as we have a nearing deadline for migration from sqlserver to Oracle

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 15-Sep-2006 17:03:17   

A NUMBER(11,0) converts to Int64, so instead of: case "OracleDbType.Int64":

you should do: case "Int64":

you can debug your typeconverter code if you want. Place the .pdb file of the typeconverter (debug build) in the folder as well. then place a breakpoint in the typeconverter code where you want to break, then specify in VS.NET that you want to debug an application instead of a project for the typeconverter project. (so when you press F5, you will run the application and the debugger should attach to that program). This is done in the project properties of the typeconverter project in vs.net. As the program you specify llblgenpro.exe. Then press F5 and the debugger should start, llblgen pro should start and you should hit the breakpoint.

Frans Bouma | Lead developer LLBLGen Pro
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 16-Sep-2006 09:54:16   

But how do I get my class as a new item in the conmbo box of the Edit Type conversion window in LLBLGEN so that I chose that and set to the field for the entities?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 16-Sep-2006 19:31:52   

Subbu wrote:

But how do I get my class as a new item in the conmbo box of the Edit Type conversion window in LLBLGEN so that I chose that and set to the field for the entities?

That's automatic, once the typeconverter is reporting that it can convert a value. Yours checked for the wrong type.

Frans Bouma | Lead developer LLBLGen Pro
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 18-Sep-2006 12:23:47   

simple_smile Thank you. simple_smile The problem is solved. I used Int64 instead of OracleDBType.Int64 and the dll got refered in LLBLGEN.

I have one more question. Can I have two classes like NumberToInt32 and NumberToIn16 , first one converting Int64 to Int32 and the second one converting Int32 to Int16 under a same namespace DBType2NETType.TypeConverters. so that I can use the appropriate classes for required type conversion.

I tried converting Int32 to Int16, it is always setting destination .nettype to Int32. Similarly in the case of Int64 to Int16 it is defaulting the destination type to Int32. Is it a limitation I can convert number types only to Int32?

Answers to this query at the earliest will be greatly appreciated.

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 19-Sep-2006 06:43:45   

Did you try to have all your options in the same class. Like the folowing:

public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
        {
            switch ( sourceType.FullName )
            {
                case "System.Int64":
                case "System.Int32":
                    return true;
                default:
                    return false;
            }
        }

        public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
        {
            switch ( destinationType.FullName )
            {
                case "System.Int32":
                case "System.Int16":
                    return true;
                default:
                    return false;
            }
        }

And then use the same switching in the ConvertFrom & ConvertTo methods.

Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 19-Sep-2006 07:21:13   

Yes I tried even that way. But it didn't help. confused confused Solution to this will make me smile I am not getting Int32 converted to Int16 I am sending my code

using System; using System.Text; using System.ComponentModel; using Oracle.DataAccess.Client; namespace DBType2NETType.TypeConverters {

public class NumberToInt : TypeConverter
{
    public NumberToInt ()
    {
    }

    public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
    {
        switch ( sourceType.FullName )
        {
            case "System.Int64":
            case "System.Int32":
                return true;
            default:
                return false;
        }
    }

    public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
    {
        switch ( destinationType.FullName )
        {
            case "System.Int32":
            case "System.Int16":
                return true;
            default:
                return false;
        }
    }

    public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value )
    {           
        int returnValueInt = 0;
        short returnValueShort = 0;
        switch ( value.GetType().FullName )
        {
            case "System.Int64":
                returnValueInt = Convert.ToInt32(value);
                return returnValueInt;
            case "System.Int32":
                returnValueShort = Convert.ToInt16(value);
                return returnValueShort;
            default:
                throw new NotSupportedException( "Conversion from a value of type '" + value.GetType().ToString() + "' to System.Int32 isn't supported" );
        }

    }

    public override object ConvertTo( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType )
    {
        int requiredValueInt = 0;
        short requiredValueShort = 0;
        if ( value == null )
        {
            throw new ArgumentNullException( "value", "Value can't be null" );
        }

// if ( !( value is Int32) ) // { // throw new ArgumentException( "Value isn't of type Int32", "value" ); // }

        switch ( destinationType.FullName )
        {
            case "System.Int32":
                requiredValueInt = Convert.ToInt32(value);
                return requiredValueInt;
            case "System.Int16":
                requiredValueShort = Convert.ToInt16(value);
                return requiredValueShort;
            default:
                throw new NotSupportedException( "Conversion to a value of type '" + destinationType.ToString() + "' isn't supported" );
        }
    }


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

}

}

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 19-Sep-2006 07:54:36   

The ConvertTo method should have this instead:

switch ( destinationType.FullName )
            {
                case "System.Int32":
                    return Convert.ToInt64(value);
                case "System.Int16":
                    return Convert.ToInt32(value);
               default:
                    throw new NotSupportedException( "Conversion to a value of type '" + destinationType.ToString() + "' isn't supported" );
            }

Since this method is used to convert from the application .Net DataType to the DataType that your database understands.

While the ConvertFrom() is used to convert from the types returnd from the database to the types you want to have in your application.

Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 19-Sep-2006 08:07:45   

It didn't work.

I am not getting System.Int16 in my Resulting .netType

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 19-Sep-2006 08:41:40   

My code example had some problems: Please try this one.

    
        public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
        {
            switch ( sourceType.FullName )
            {
                case "System.Int64":
                case "System.Int32":
                    return true;
                default:
                    return false;
            }
        }

        public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
        {
            switch ( destinationType.FullName )
            {
                case "System.Int64":
                case "System.Int32":
                    return true;
                default:
                    return false;
            }
        }

        public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value )
        { 
            switch ( value.GetType().FullName )
            {
                case "System.Int64":
                    return Convert.ToInt32(value);
                case "System.Int32":
                    return Convert.ToInt16(value);
                default:
                    throw new NotSupportedException( "Conversion from a value of type '" + value.GetType().ToString() + "'  isn't supported" );
            }           
        }

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

            switch ( destinationType.FullName )
            {
                case "System.Int64":
                    return Convert.ToInt64(value);
                case "System.Int32":
                    return Convert.ToInt32(value);
                default:
                    throw new NotSupportedException( "Conversion to a value of type '" + destinationType.ToString() + "' isn't supported" );
            }
        }

(edit) Please note this tip: The sourceTypes of the ConvertFrom method (value.GetType().FullName) should be the same as those destinationTypes in the ConvertTo method (destinationType.FullName)

Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 19-Sep-2006 09:04:31   

I used your code. I am sending the table which we see in the edit type conversion window below.

Defined type conversions

.Net Type to convert Type Converter Resulting .NET type DBType Length **System.Int32 DBType2NETType.TypeConverters System.Int32 Number 6 ** System.Int64 DBType2NETType.TypeConverters System.Int32 Number 11

How do I get System.Int16 in the Resulting .NET type for Source Int32(the row in bold letters)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 19-Sep-2006 09:33:16   

Did the code work or didn't it work? Walaa's code looks like the code you need.

Another question: Why not alter the NUMBER() definitions in the schema so they match what you need for .NET types?

Frans Bouma | Lead developer LLBLGen Pro
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 19-Sep-2006 09:39:46   

The code is building properly and I am getting the reference item in the LLBLGEN GUI. When I select Int32 or Int64 i am getting this class name in the dropdown of edit type conversion window.

But the resultant .net type is always deaulting to Int32. it is not changing to Int16. I need this to change to Int16

I cannot go with changing the field database type to match with .net type, b'cos I used Number(6) in Oracle to match with smallint for MSSQLServer. If I have to match with .net type it should be Number(4) in Oracle so that I can store a maximum of 9999 in Oracle whereas smallInt in MSSQL can store upto 32767. Upto Number(4) LLBLGEN converts to Int16.

I am using the code which walaa sent. public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value ) { switch ( value.GetType().FullName ) { case "System.Int64": return Convert.ToInt32(value); case "System.Int32": return Convert.ToInt16(value); default: throw new NotSupportedException( "Conversion from a value of type '" + value.GetType().ToString() + "' isn't supported" ); } }

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

        switch ( destinationType.FullName )
        {
            case "System.Int64":
                return Convert.ToInt64(value);
            case "System.Int32":
                return Convert.ToInt32(value);
            default:
                throw new NotSupportedException( "Conversion to a value of type '" + destinationType.ToString() + "' isn't supported" );
        }
    }
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39866
Joined: 17-Aug-2003
# Posted on: 19-Sep-2006 11:12:53   

Subbu wrote:

The code is building properly and I am getting the reference item in the LLBLGEN GUI. When I select Int32 or Int64 i am getting this class name in the dropdown of edit type conversion window.

But the resultant .net type is always deaulting to Int32. it is not changing to Int16. I need this to change to Int16

I cannot go with changing the field database type to match with .net type, b'cos I used Number(6) in Oracle to match with smallint for MSSQLServer. If I have to match with .net type it should be Number(4) in Oracle so that I can store a maximum of 9999 in Oracle whereas smallInt in MSSQL can store upto 32767. Upto Number(4) LLBLGEN converts to Int16.

Ah. Ok, I bit of a misunderstanding here.

A type converter has ONE destination type. You can't make a type converter which has two destination types. So in your case, you have to make TWO type converters: one which converts to Int32 and one which converts to Int16. The one which converts to Int32 accepts Int64 values and should return 0 from the CreateInstance method. The one which converts to Int16 should accept Int32 values and should return (short)0 from the CreateInstance method. It's important you return a short (int16) from the createinstance method, because that's the way the destination type is determined.

Frans Bouma | Lead developer LLBLGen Pro
Subbu avatar
Subbu
User
Posts: 13
Joined: 02-Mar-2006
# Posted on: 19-Sep-2006 12:14:33   

This did the magic sunglasses

It is converting Int32 to Int16.

Thank you Otis. It will help us really a lot in the migration work