Search code examples
c#sql.net-coreautomappermysql.data

AutoMapper MapFrom can't take null values


I have a column session_expires_at in my person database table. This column is of type DATETIME and is nullable. In my code my User object represents this column with

public DateTime? SessionExpiresAt { get; set; }

When reading the user from the database with the MySQL.Data package I want to use AutoMapper to map the database result to the User object.

CreateMap<DbDataReader, User>()
    .ForMember(user => user.SessionExpiresAt,
        memberOptions => memberOptions.MapFrom(dbDataReader => dbDataReader.IsDBNull(1) ? null : dbDataReader.GetDateTime(1)));

Since I know this value might be null I'm running a check before to avoid an exception. If that data is null, I want to assign null to the property, otherwise the datetime value. Unfortunately this error shows up

There is no implicit conversion between 'null' and 'System.DateTime'

I played around a little bit and the MapFrom method is not able to take a null value. So if I would do this

CreateMap<DbDataReader, User>()
    .ForMember(user => user.SessionExpiresAt, memberOptions => memberOptions.MapFrom(dbDataReader => null));

I get this error

The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly

I also tried this but it didn't help

CreateMap<DbDataReader, User>()
    .ForMember(user => user.SessionExpiresAt,
        memberOptions =>
        {
            memberOptions.AllowNull();
            memberOptions.MapFrom(dbDataReader => dbDataReader.GetDateTime(1));
        });

It is not possible for me to take a default value like DateTime.Now if the database value is null. It has to be possible to assign a null value.

How can I fix it so that I can assign null values to the property within the mapping rule? Maybe I can disable the mapping process if the value is null so it won't assign something?


Solution

  • As others already mentioned in comments, your MapFrom() logic didn't work because of type mismatch between null and DateTime, as DateTime cannot be null. Only nullable DateTime can, so instead of using null you should use (DateTime)null or default(DateTime?).

    CreateMap<DbDataReader, User>()
        .ForMember(
            user => user.SessionExpiresAt,
            options => options.MapFrom(dbDataReader => dbDataReader.IsDBNull(1) ? default(DateTime?) : dbDataReader.GetDateTime(1)));
    

    Another way and maybe a bit more readable is to use PreCondition(), where you can check before the actual mapping if the particular value from reader is null. If it is, the mapping for SessionExpiresAt will not happen.

    CreateMap<DbDataReader, User>()
        .ForMember(
            user => user.SessionExpiresAt,
            options =>
            {
                options.PreCondition(dbDataReader => !dbDataReader.IsDBNull(1));
                options.MapFrom(dbDataReader => dbDataReader.GetDateTime(1));
            });