0

I wanted to map a data table to a Model. And I used AutoMapper to do the job. I wrote I unit test using NUnit. This is how I did it

The model

public class DataTableModelTest
{
    public int Dosage { get; set; }
    public string Drug { get; set; }
}

Mapper Method

class MapperClass{
   public IList<TResultType> MapToModel<TResultType>(DataTable datatable)
    {
        AutoMapper.Mapper.Reset();
        AutoMapper.Mapper.CreateMap<IDataReader, IList<TResultType>>();

        var re = AutoMapper.Mapper.Map<IDataReader, IList<TResultType>>(datatable.CreateDataReader());
        return re;
    }
}

The unit test for the Mapper

[Test]
public void TestTheJob() // don't mind the method name
    {
        const int expectedListCount = 3;

        var dataTables = GetDataTable();

        var mapperClass = new MapperClass();

        var result = mapperClass.MapToModel<DataTable>(dataTables);

        Assert.AreEqual(expectedListCount, result.Count);
    }

Data table getter.. this is included with the unit test

public DataTable GetDataTable()
{
    var dataTable = new DataTable();

    dataTable.Columns.Add("Drug", typeof(string));
    dataTable.Columns.Add("Dosage", typeof(int));

    dataTable.Rows.Add("Indocin", 25);
    dataTable.Rows.Add("Enebrel", 50);
    dataTable.Rows.Add("Hydralazine", 10);

    return dataTable;
 }

THE PROBLEM

enter image description here

What am I missing?

FYI: I'm using the latest stable version of AutoMapper 6.1.1 and NUnit version 3.8.1

ash
  • 2,902
  • 3
  • 19
  • 34

2 Answers2

1

You are creating a mapping between an IDataReader and IList<TResultType> as follows:

AutoMapper.Mapper.CreateMap<IDataReader, IList<TResultType>>();

but then you are mapping a DataTable to the `IList

Try changing this...

AutoMapper.Mapper.CreateMap<IDataReader, IList<TResultType>>();

to this

AutoMapper.Mapper.CreateMap<DataTable, IList<TResultType>>();

Please refer to the MSDN documentation for the DataTable class to see the inheritance tree for this type: https://msdn.microsoft.com/en-us/library/system.data.datatable(v=vs.110).aspx

In addition, AutoMapper does not by default know how to perform mappings between DataTable columns and type properties. You will have to explicitly define these mappings. Please refer to this SO answer as to how you can achieve this Using AutoMapper to Map a DataTable to an Object (DTO)

CShark
  • 2,183
  • 1
  • 24
  • 42
  • @ash Were you able to sort out this issue? – CShark Oct 24 '17 at 15:13
  • Yes. but instead of using AutoMapper.. I used reflection by following this SO question https://stackoverflow.com/questions/12662318/how-to-convert-datatable-to-listt-using-reflections – ash Oct 24 '17 at 15:48
  • I would recommend using this method instead, since reflection tends to incur performance overhead https://stackoverflow.com/questions/208532/how-do-you-convert-a-datatable-into-a-generic-list – CShark Oct 24 '17 at 15:52
  • I checked your suggestion. But which answer are you referring to. Most of them use reflection... and some of them used the method for specific class.. not generic and some answer just showed how to return DataRows. Check out my solution here – ash Oct 24 '17 at 16:15
  • I am referring to Jon Skeet's answer. Convert a datatable to a List collection, and then using LINQ Select() map your individual columns to your output object's attributes. However, if your current method works for your situation then that is also fine ;) – CShark Oct 24 '17 at 18:35
0

Instead of using Automapper... I used reflection by referring this SO

public IList<TResultType> MapDataTableToType<TResultType>(DataTable dataTable) where TResultType : class, new()
{
    var list = new List<TResultType>();

    foreach (var row in dataTable.AsEnumerable())
    {
        var obj = new TResultType();

        foreach (var prop in obj.GetType().GetProperties())
        {
            var propertyInfo = obj.GetType().GetProperty(prop.Name);
            if (propertyInfo != null)
                propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
            }

            list.Add(obj);
        }

        return list;
    }
}
ash
  • 2,902
  • 3
  • 19
  • 34