简体   繁体   中英

Converting string to bool within DataReader with Automapper

This seems like a very simple question, so hopefully this will be easy.

I have a custom string to bool map in Automapper that simply converts "Y" and "N" to true and false . It doesn't get much simpler:

Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");

This works fine in this primitive example:

public class Source
{
    public string IsFoo { get; set; }
    public string Bar { get; set; }
    public string Quux { get; set; }
}

public class Dest
{
    public bool IsFoo { get; set; }
    public string Bar { get; set; }
    public int Quux { get; set; }
}

// ...

Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");
Mapper.CreateMap<Source, Dest>();
Mapper.AssertConfigurationIsValid();

Source s = new Source { IsFoo = "Y", Bar = "Hello World!", Quux = "1" };
Source s2 = new Source { IsFoo = "N", Bar = "Hello Again!", Quux = "2" };
Dest d = Mapper.Map<Source, Dest>(s);
Dest d2 = Mapper.Map<Source, Dest>(s2);

However, let's say instead I want to take the Source data from a DataReader :

Mapper.CreateMap<string, bool>().ConvertUsing(str => str.ToUpper() == "Y");
Mapper.CreateMap<IDataReader, Dest>();
Mapper.AssertConfigurationIsValid();

DataReader reader = GetSourceData();
List<Dest> mapped = Mapper.Map<IDataReader, List<Dest>>(reader);

For every Dest in mapped , the IsFoo property is true . What am I missing here?

I ended up ditching the string to bool map and instead creating extension methods for IMemberConfigurationExpression<IDataReader> . Extension methods plural because I also ran into this issue where numerical data coming back from the DB didn't match the destination types perfectly, causing inconsistent large numbers. Since the database stuff was out of my control, I had to force the mapper to read it as a certain type. So here's what I ended up with:

public static class Mapping
{
    public static void Init()
    {
        Mapper.CreateMap<IDataReader, Dest>()
            .ForMember(s => s.IsFoo, opt => opt.ReadAsBoolean("IsFoo"))
            .ForMember(s => s.Quux, opt => opt.ReadAsNumber("Quux"));

        Mapper.AssertConfigurationIsValid();
    }

    public static void ReadAsBoolean(this IMemberConfigurationExpression<IDataReader> opt, string fieldName)
    {
        opt.MapFrom(reader => reader.GetString(reader.GetOrdinal(fieldName)).ToUpper() == "Y");
    }

    public static void ReadAsNumber(this IMemberConfigurationExpression<IDataReader> opt, string fieldName)
    {
        opt.MapFrom(reader => reader.GetDecimal(reader.GetOrdinal(fieldName)));
    }
}

The duplication of the property names as strings goes against my grain, but I suspect someone with more Automapper skills could make that more elegant. For now, this at least works.

Inside the IDataReader the data is stored as objects and not strings. So I'm assuming AutoMapper is evaluating anything that is not null as true .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM