Can dapper handle enums stored as varchar in the database if there's an explicit constructor defined?

.net dapper enums

Question

I have a class containing a field of an enum type.

enum myEnum { foo, bar }

class myClass {
    ...

    public myClass(myEnum myField)
    {
        this.myField =myField;
    }
    public myEnum myField {get;set;}
}

The enum values are stored in the database as varchars (ie 'foo',bar'), not as integers.

I'd like to user dapper to dapperQuery() to populate my objects, but can't get it to work, Dapper keeps complaining it didn't find a suitable constructor for myClass

I've read this question, and it seems to imply that what I want to achieve should be possible, but I just can't see how (I'm using Dapper 1.38)

I've tried adding a TypeHandler for myEnum, but it didn't help.

When I look under the hood it seems Dapper searches for a TypeHandler for myClass (in SqlMapper.GetDeserializer() ), doesn't find any (as my TypeHandler is defined for myEnum, and proceeds to calling SqlMapper.FindConstructor

Findconstructor doesn't seem to bother about typeHandlers, it just looks for an exact match, checks whether myEnum or it's underlying type is the same type as string, figures out that it's not, returns null, and the caller throws...

Edit : The above code works if you remove the explicit constructor.

Accepted Answer

Ok, I figured it out. It seems dapper cannot cope with enums if there's a non-default constructor defined.

This is because dapper has a special case to handle parameterless constructors (they are automatically considered valid) whereas explicit constructors are type checked and are not accepted in my varchar - enum scenario.

The reason why it's important is F# Record Types, which can't have any constructors beside the default one, and thus aren't handled properly by Dapper when they contain enum members.

I have submitted a pull request to fix this issue.


Popular Answer

Seems to be working OK. Below test is green:

public enum MyTestEnum
{
    Foo,
    Bar
}

public class MyTestClass
{
    public MyTestEnum MyTestEnum { get; set; }
}

public class DapperTests
{
    [Test]
    public void EnumMappingTest()
    {
        DbConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);

        var result = conn.Query<MyTestClass>("select MyTestEnum = 'Foo'").First();

        Assert.That(result.MyTestEnum, Is.EqualTo(MyTestEnum.Foo));
    }
}



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why