21

I am trying to map a DataTable to an object (DTO) using AutoMappers DynamicMap feature.

DataTable dt;
dt = new dalAllInvestors().InvestorNameSearch(investorNameSearch);

// Look at DynamicMap - Urgent 
List<dtoAPISimpleInvestor> apiObject = AutoMapper.Mapper.DynamicMap<IDataReader, List<dtoAPISimpleInvestor>>(
dt.CreateDataReader());

return apiObject;


public class dtoAPISimpleInvestor
{
    public int FirmID { get; set; }
    public string FirmName { get; set; }
    public string Type { get; set; }
    public string Location { get; set; }
}

dt returns 10 rows but when you look at the apiObject it returns no rows and this does not seem to make any sense. I have been looking at this for a while now and after googling it looks like I am doing it correctly.

The correct columns are in the dt when its return which map to the dtoAPISimpleInvestor

Can somebody please help me?

halfer
  • 19,824
  • 17
  • 99
  • 186
DJB
  • 303
  • 2
  • 3
  • 6

2 Answers2

24

How about something like the following...

AutoMapper Profile

public sealed class SimpleInvestorProfile : Profile
{
  // This is the approach starting with version 5
  public SimpleInvestorProfile()
  {
      IMappingExpression<DataRow, dtoAPISimpleInvestor> mappingExpression;

    mappingExpression = CreateMap<DataRow, dtoAPISimpleInvestor>();
    mappingExpression.ForMember(d => d.FirmID, o => o.MapFrom(s => s["FirmID"]));
    mappingExpression.ForMember(d => d.FirmName, o => o.MapFrom(s => s["FirmName"]));
    mappingExpression.ForMember(d => d.Type, o => o.MapFrom(s => s["Type"]));
    mappingExpression.ForMember(d => d.Location, o => o.MapFrom(s => s["Location"]));

  }

  // this method is obsolete in version 5
  // protected override void Configure()
  // {
  //   IMappingExpression<DataRow, dtoAPISimpleInvestor> mappingExpression;

  //  mappingExpression = CreateMap<DataRow, dtoAPISimpleInvestor>();
  //  mappingExpression.ForMember(d => d.FirmID, o => o.MapFrom(s => s["FirmID"]));
  //  mappingExpression.ForMember(d => d.FirmName, o => o.MapFrom(s => s["FirmName"]));
  //   mappingExpression.ForMember(d => d.Type, o => o.MapFrom(s => s["Type"]));
  //  mappingExpression.ForMember(d => d.Location, o => o.MapFrom(s => s["Location"]));

  //  return;
 // }
}

NOTE : I am using the DataRow type as the source and not IDataReader (more on this below).

Using the Profile

MapperConfiguration configuration;

configuration = new MapperConfiguration(a => {a.AddProfile(new SimpleInvestorProfile());});

IMapper mapper;

mapper = configuration.CreateMapper();

List<dtoAPISimpleInvestor> result;

result = mapper.Map<List<DataRow>, List<dtoAPISimpleInvestor>>(rows);

The result object should contain the correct number of dtoAPISimpleInvestor objects with the correct data.

NOTE : The call to mapper.Map takes an object of type List<DataRow> which can be obtained from the DataTable object using the statement new List<DataRow>(dataTable.Rows.OfType<DataRow>()); (since the Rows property of the DataTable object is a collection that implements IEnumerable but not IEnumerable<T>).

This is likely not the only solution but I have validated that it works.

As a side note, I noticed that DynamicMap method that you referenced has been marked as obsolete in the latest version of the library so you may want to avoid using it.

Dhaval Asodariya
  • 558
  • 5
  • 19
Jason Richmeier
  • 1,595
  • 3
  • 19
  • 38
  • I get Argument 1: cannot convert from 'System.Data.DataRowCollection' to 'System.Collections.Generic.List – Rudy Hinojosa Nov 29 '17 at 17:24
  • 2
    ok, this worked using result = mapper.Map, List>(yourdatatable.AsEnumerable().ToL‌​ist()); – Rudy Hinojosa Nov 29 '17 at 19:16
  • Add a reference to `System.Data.DataTableExtensions` for `.AsEnumberable()`, [source](https://social.msdn.microsoft.com/Forums/en-US/d959dda9-02f7-4182-bbb3-04b3459388c7/datatableasenumerable-missing?forum=csharplanguage) – spottedmahn Aug 15 '18 at 15:40
6

This worked for me: Version of automapper is 3.1.1 download from nuget

using AutoMapper;

public List<T> ReadData<T>(DataTable dt)
{            
  return Mapper.DynamicMap<IDataReader, List<T>>(dt.CreateDataReader());                        
}

Call method like this:

DataTable dt = getPeopleDT();
List<PEOPLEDTO> peopleList = ReadData<PEOPLEDTO>(dt);   
WEFX
  • 8,298
  • 8
  • 66
  • 102
Xtian11
  • 2,130
  • 1
  • 21
  • 13