How to Access Dapper Results When Using Dynamic Due to Enum

1

I have a Dapper DB call that has a column that maps to an enum on the type. From what I understand, I have to query using dynamic because the query can't map to my Request type since Status is an enum on it. So I tried using this:

public async Task<Request> GetByRequestId(long id)
{
    string sql = "SELECT * FROM Request WHERE ID = @id";

    using (var connection = new SqlConnection(_connectionString))
    {
        // Need dynamic here because of the conversion of the Status column as an enum.
        // If someone has a better way...
        dynamic dynamicRequest = await connection.QueryFirstOrDefaultAsync(sql, new { id });
        if (dynamicRequest == null) { return default; }

        var request = new Request
        {
            Id = dynamicRequest.ID,
            Status = (RequestStatus)Enum.Parse(typeof(RequestStatus), dynamicRequest.Status)
        };

        return request;
    }
}

However, I can't access any of the properties on the dynamic object, called dynamicRequest. When debugging, I can see its value like this:

{{DapperRow, ID = '8', FooID = '12', Status = 'N'}}

How can I access ID, or FooID, or Status? This doesn't work:

dynamicRequest.ID
dynamicRequest[0]
dynamicRequest["ID"]
// and many other tries...

This is the error I get if I try using the actual class, instead of dynamic:

System.Data.DataException HResult=0x80131501 Message=Error parsing column 4 (Status=N - String) ArgumentException: Requested value 'N' was not found.

And this is the enum. I just added the JsonConverter attribute to try and get this to work with the actual Request class.

[JsonConverter(typeof(StringEnumConverter))]
public enum RequestStatus
{
    [EnumMember(Value = "N")]
    New = 1,

    [EnumMember(Value = "A")]
    Approved = 2,

    [EnumMember(Value = "C")]
    Cancelled = 3,

    [EnumMember(Value = "D")]
    Declined = 4,

    [EnumMember(Value = "P")]
    Pending = 5,
}

Here is a screenshot of dynamicRequest and an attempt at accessing the ID property.

enter image description here

c#
dynamic
dapper
asked on Stack Overflow Feb 12, 2020 by Bob Horn • edited Feb 12, 2020 by Bob Horn

1 Answer

2

Your problem is the Enum.Parse doesn't honor your EnumMember attributes.

This works however.

public static async Task<Request> GetByRequestId(long id)
{
    string sql = "SELECT * FROM Request WHERE ID = @id";

    using (var connection = new SqlConnection(_connectionString))
    {
        // Need dynamic here because of the conversion of the Status column as an enum.
        // If someone has a better way...
        dynamic dynamicRequest = await connection.QueryFirstOrDefaultAsync(sql, new { id });
        if (dynamicRequest == null) { return default; }

        var request = new Request
        {
            Id     = dynamicRequest.ID,
            Status = JsonConvert.DeserializeObject<RequestStatus>($"\"{dynamicRequest.Status}\""),
        };

        return request;
    }
}

Running I get...

enter image description here

Then the mapped Request...

enter image description here

This is what my database table looks like...

enter image description here

answered on Stack Overflow Feb 12, 2020 by Jim • edited Feb 12, 2020 by Jim

User contributions licensed under CC BY-SA 3.0