Skip to content

Reading nullable DateTime fails when the column has a non-null value #295

Closed
@ngeor

Description

@ngeor

I'm using MySql database and the NuGet version of Dapper. I'm reading from the database like this:

return _connection.Query<Person>(
    "SELECT * FROM Person WHERE PersonId=@PersonId",
    new { PersonId = 42 }).SingleOrDefault();

The class contains a nullable DateTime property. When the value is NULL in the database, it works fine. When it has a value, it fails complaining:

Error parsing column 14 (LastCommentedAt= - Object)

I managed to solve this by installing my own TypeHandler for DateTime?. I saw how Dapper.NodaTime is doing it so I created my own handler:

public class NullableDateTimeHandler : SqlMapper.TypeHandler<DateTime?>
{
    protected NullableDateTimeHandler()
    {
    }

    public static readonly NullableDateTimeHandler Default = new NullableDateTimeHandler();

    public override void SetValue(IDbDataParameter parameter, DateTime? value)
    {
        if (value.HasValue)
        {
            parameter.Value = value.Value;
        }
        else
        {
            parameter.Value = DBNull.Value;
        }
    }

    public override DateTime? Parse(object value)
    {
        if (value == null)
        {
            return null;
        }

        if (value is DateTime)
        {
            return (DateTime)value;
        }

        return Convert.ToDateTime(value);
    }
}

and I make sure I install this handler before anything else happens:

SqlMapper.AddTypeHandler(NullableDateTimeHandler.Default);

With this in place, I can read nullable dates correctly whether they have a NULL value or an actual value. I think this should be built-in functionality provided by Dapper, so I'm raising this ticket.

The stacktrace I get without my workaround looks like this:

MESSAGE:
System.Data.DataException : Error parsing column 14 (LastCommentedAt= - Object)
  ----> System.InvalidCastException : Cannot cast from source type to destination type.
+++++++++++++++++++
STACK TRACE:
at Dapper.SqlMapper.ThrowDataException (System.Exception,int,System.Data.IDataReader,object) <0x002e7>
at (wrapper dynamic-method) object.Deserializedf762666-acf8-4d08-832f-f40f4dc76cd7 (System.Data.IDataReader) <0x0105e>
at Dapper.SqlMapper/<QueryImpl>d__61`1<Person>.MoveNext () <0x006c3>
at System.Collections.Generic.List`1<Person>.AddEnumerable (System.Collections.Generic.IEnumerable`1<Person>) <0x0008f>
at System.Collections.Generic.List`1<Person>..ctor (System.Collections.Generic.IEnumerable`1<Person>) <0x000d5>
at System.Linq.Enumerable.ToList<Person> (System.Collections.Generic.IEnumerable`1<Person> <0x0004b>
at Dapper.SqlMapper.Query<Person> (System.Data.IDbConnection,string,object,System.Data.IDbTransaction,bool,System.Nullable`1<int>,System.Nullable`1<System.Data.CommandType>) <0x001fb>
at PersonDataLayer.Read (int) <0x0007f>
at PersonTests.TestCreate () <0x004ef>

--InvalidCastException
at System.Nullable`1<System.DateTime>.Unbox (object) <0x00081>
at (wrapper dynamic-method) object.Deserializedf762666-acf8-4d08-832f-f40f4dc76cd7 (System.Data.IDataReader) <0x00f3d>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions