Cannot use converter for enum

Posts   
 
    
PawelO
User
Posts: 3
Joined: 08-Feb-2012
# Posted on: 28-Dec-2015 11:06:05   

Hi, I'm using Llblgen Pro 4.2 (nov 19 2014) in postgresql (9.4.4) and npgsql (tried 3.0.4 and 2.2.0). I've got enum in db CREATE TYPE xxxx.someStatus AS ENUM (''test1'', ''test2''); It's typeimported and visible in imported types, Also I've written some converters for this enum, and they are also visible (tried both ways System.String to namespace.someStatus and back , also "varchar" to someStatus ). After setting in designer type to someStatus there is error "The .NET types of the mapped element field and the target field aren't the same/compatible, so converter is needed" but none of created converter is visible on list of converters to use at that field.

Without setting Enum type at someStatus I got "An exception was caught during the execution of an action query: 42804: column \"ready_status\" is of type xxx.someStatus but expression is of type text."

The enum looks like [Serializable] [DataContract] public enum someStatus { [EnumMember] test1, [EnumMember] test2 }

Am I missing something to get it working?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 28-Dec-2015 23:26:41   

Could you please share the TypeConverter code?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39922
Joined: 17-Aug-2003
# Posted on: 29-Dec-2015 10:45:13   

The enum typed field in the entity has to be mapped to a field in the database which is of type 'int' or 'long'. Is that the case? It looks like your entity field is mapped to a field which is of a different type (e.g. decimal or string)

Frans Bouma | Lead developer LLBLGen Pro
PawelO
User
Posts: 3
Joined: 08-Feb-2012
# Posted on: 29-Dec-2015 15:28:39   

I had a wrong return type in CreateInstance, after fixing the converter looks like


    public class SomeConverterConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType.FullName == "System.String")
            {
                return true;
            }

            return false;
        }
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType.FullName == "xxx.someStatus ")
            {
                return true;
            }

            return false;
        }
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value == DBNull.Value
                || value == null)
            {
                return null;
            }
            if(Enum.GetName(typeof(someStatus ), someStatus .test1 ) == value.ToString())
            { return someStatus .test1; }
            else 
            {
                return someStatus .test2;
            }

        }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (value == DBNull.Value
                || value == null)
            {
                return null;
            }
            return Enum.GetName(typeof(someStatus ), value);
        }
        public override object CreateInstance(ITypeDescriptorContext context, System.Collections.IDictionary propertyValues)
        {
            return someStatus .test2;
        }

as previous is visible in tools but now can be applied to conversion.

After using it to conversion the reading is no problem, but while save i got:

An exception was caught during the execution of an action query: 42804: column \"ready_status\" is of type testenum.ready_status but expression is of type character varying. Check InnerException, QueryExecuted and Parameters of this exception to examine the ...

the query looks like

    Query: UPDATE "test"."testenum" SET "modified_at"=NOW() at time zone 'utc' + '5s', "ready_status"=:p1 WHERE ( "test"."testenum"."id" = :p2)
    Parameter: :p1 : String. Length: 10485760. Precision: 0. Scale: 0. Direction: Input. Value: "test1".
    Parameter: :p2 : Int64. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: 181828831.
    
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39922
Joined: 17-Aug-2003
# Posted on: 29-Dec-2015 15:40:18   

You don't need a converter for the enum: if the table field is an int, it's automatic. I don't know what type the table is, as you didn't mention that. Is it of type 'ENUM' in the DB? As that isn't a supported DB type (but int is).

So please give more specifics as we can't help you with the info you gave us: in the designer what's the type of the table field the entity field is mapped on? (it's in the fields mappings tab, and you can also see the type in the catalog explorer-> select Fields of the table and right-click -> show details).

Am I correct it's of type testenum.ready_status, which is a native Postgresql type? That's not the same as the someStatus .NET type, as testenum.read_status is a postgresql type, not a .NET type. So if that's the case: define the column as int in the table as the postgresql type isn't usable in .NET, only in the DB.

Frans Bouma | Lead developer LLBLGen Pro
PawelO
User
Posts: 3
Joined: 08-Feb-2012
# Posted on: 29-Dec-2015 16:14:53   

The column ready_status is of type someStatus and the type was created by CREATE TYPE xxxx.someStatus AS ENUM (''test1'', ''test2''). The field mapping looks like: .NET type System.String DB type varchar Max lenght 10485760 But in fields Tab the Type is specified to xxx.SomeStatus

So I guess you are correct with

Am I correct it's of type testenum.ready_status, which is a native Postgresql type

but I thought that converter would handle this one as

UPDATE testenum.ready_status
   SET  ready_status= 'block'
 WHERE id =181828831

works fine.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39922
Joined: 17-Aug-2003
# Posted on: 30-Dec-2015 09:11:14   

Type converters work in the .NET space, so they convert a value from an entity field (which is a .NET typed value) into another .NET type and then place that value into a parameter. Vice versa, they convert the .NET typed value from the datareader into another .NET typed value and place that in the entity field. So they don't convert .NET types into native DB types.

The db parameter -> dbtype conversion could lead to the result you want (e.g. string to varchar is implicit and thus works), but as I don't know how DB native enums are converted to .NET types (I don't see how that could be done, as .NET types are compiled types and thus not changeable) I don't see how that's going to work.

Frans Bouma | Lead developer LLBLGen Pro