RepoDB icon indicating copy to clipboard operation
RepoDB copied to clipboard

Question: Handling of enums

Open ghost opened this issue 5 years ago • 6 comments

Hi,

Before 1.10 I could use:

[TypeMap(DbType.Int32)] public LeadStatus Status { get; set; }

But this now fails, as the Status value retrieved from Db for some reason is NULL (it's 0)

public int Status { get; set; }

Gives me the right integer value for sure, but would like to work directly with the enum. Is this a bug or has enum mapping/translation changed?

Best, CU

ghost avatar Oct 02 '20 10:10 ghost

After debugging a little I could see that it now uses the "enum name" and not the "property name" when mapping to DB model.

So after a little renaming it works.

[TypeMap(DbType.Int32)] public Status LeadStatus { get; set; }

Is this a deliberate choice of change or?

ghost avatar Oct 02 '20 10:10 ghost

@Kodestuen - we have rewritten our core compilers from scratch and the intention is to pass all the existing Integration Tests without doing any change on it. But I remember, we have made some changes (because we are required to) on the compiler's behavior to accommodate and override the ADO.NET default coercion. It is because it is failing in the PostgreSQL driver.

Though, we would say that the change in behavior is not deliberate. But we made an improvements on this area, the RepoDB is now more intelligent when parsing the Enums.

On the new compiler, you do not need to define the TypeMap attribute and it will just wok like a charm. I would recommend, just use your old code and just remove the attribute.

public LeadStatus Status { get; set; }

Would you be able to check it?

mikependon avatar Oct 02 '20 12:10 mikependon

Some changes happens on the compiler level, at this Enum.GetName(), and is reusing this Enum.Parse() method, in which the compiler does the following for you automatically.

var name = Enum.GetName(typeof(YourEnumType), value);
var value = Enum.Parse(typeof(YourEnumType), name, true);
YourClassType.EnumProperty = value;

Therefore, you do need to dictate the DbType.

The same behaviour also exists if you are pushing a value of the Enum to an INT column or a NVARCHAR column.

mikependon avatar Oct 02 '20 12:10 mikependon

Indeed that works!

public LeadStatus Status { get; set; }

Thanks for clarifying :-)

ghost avatar Oct 02 '20 12:10 ghost

Thanks for verifying it. You can always test the enum coercion on the Type Result execution like below. It was a part of the latest release (v1.12.x).

var status = await connection.ExecuteQueryAsync<LeadStatus>("SELECT Status FROM YourTable;");

Such simple call defines how RepoDB handles specific coercion on a specific type.

mikependon avatar Oct 02 '20 12:10 mikependon

One more thing, one of the correct usage of the TypeMap for enum is if you really would like to deliberately save the data on that specific type.

Let us say, you have a column named Status of type NVARCHAR/TEXT and your class property Status is of type LeadStatus enum, by default, it will be retrieved/saved as String. If you want to force retrieve/save it as an Integer, then that is the time you define the TypeMap.

Hope that explains!

mikependon avatar Oct 02 '20 13:10 mikependon