How to use autoMapper for datatables to list?

I think I miss something in my code which cause this error : AutoMapperMappingException: Missing type map configuration or unsupported mapping. this is my first time that I try to use autoMapper for filling my dto from datatable. so I found an example from How do I use automapper to map a dataset with multiple tables . so this is my code :

public class ContractController : ApiController
    {
        private readonly IMapper _mapper;

        public ContractController()
        {
            var mapperConfig = new MapperConfiguration(x =>
                x.CreateMap<IDataReader, ContractListDto>());
            _mapper = mapperConfig.CreateMapper();
        }

        [Route("api/Sales/ContractsList")]
        [HttpGet]
        public IHttpActionResult  Get()
        {
            var salesHelper = new SalesHelper(enmSaleDocType.enmSaleDocType_SaleContract,
                enmSaleAfterSaleMode.enmSaleAfterSaleMode_Sale,
                enmSaleOperationType.enmSaleOperationType_Sales);
            var saleDataTable = salesHelper.GetSales();
            IEnumerable<ContractListDto> contractsDto = null;
            using (var saleDataReader = saleDataTable.CreateDataReader())
            {
                 contractsDto = _mapper.Map<IEnumerable<ContractListDto>>(saleDataReader);
            }
            
            
            return Ok(contractsDto);
        }
    }

I am utilizing api2 dotnet framework and automapper version 10. so I cannot initialize automapper in globol.asax. so I try to achieve this from constructor as you see in my code.(may I am doing something wrong there! ). at the end I get error here:
using (var saleDataReader = saleDataTable.CreateDataReader())
            {
                 contractsDto = _mapper.Map<IEnumerable<ContractListDto>>(saleDataReader);
            }

when I am trying to map. thanks for reading.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can’t use Automapper because it looks at the properties of one object here, and the properties of another object there, and copies them across. A DataRow doesn’t have any interesting properties

When you load a base, weakly typed, datatable:

var myDataTable = new DataTable();
myDataDapter.Fill(myDatatable);

You have a collection of DataRow obejcts. When you want an item of data out of a datarow, there are a variety of ways you can get it but the root process is always the same; you get it out of the object array in which it lives by passing an indexer to a collection and casting the result:
var row1 = myDatatable.Rows[0];

var personName = row1["PersonName"] as string;

There are alternative ways of writing the same thing, but ultimately this data just lives in an array, and is indexed by string/int, it needs casting to be useful. A DataRow has no PersonName property that returns a string; AUtomapper is designed to work with a PersonName property that returns a string.

As Panagiotis has been pointing out in the comments, you’ll need to do something with the datarow to make it have properties but the level of effort you go to to prepare an object that you can then use with Automapper, you might as well just skip Automapper and assign the values straight to the destination object

Example

//no
class Person{ 
  public string PersonName 
}
...
foreach(DataRow ro in someDt)
  var p = new Person();
  p.PersonName = ro["PersonName"] as string;

  var p = mapper.Map<PersonDto>(p);

All that creating a person class and assigning to its PersonName just so Automapper has something it can map to PersonDto -> pointless! Just make a new PersonDto and assign the value directly

We can make some reduced effort means of performing the same thing, which I suppose might have a use case. If you want to add a DataSet to your project you can then add a new datatable to it and specify the name and type of the properties therein. In code this then becomes a class in its own right, with properties that Automapper can use. In reality this is just Visual Studio writing a bunch of code like:

class PersonRow: DataRow

  public string PersonName {
    get{
      return this["PersonName"] as string;
    }
...

i.e. in inherits base DataRow for you and adds properties. It’s a low effort way of creating a data entity representation that still works as a DataTable/DataRow does (because it’s inherited).. so a dataadapter / ado.net can fill it, and then you can work with it using the named properties

If you’re desperate to use automapper, it’d be the way I’d go; get VS to write this boring code “make a named property that accesses an internal array of object and casts the result” for you. Each one of these things in this picture is a basic DataTable/DataRow, enhanced with named properties:

How to use autoMapper for datatables to list? (from the docs)

Theyre a lot nicer to work with than base DataTable, you can linq query them directly (personDataTable.Select(x => …)`, you don’t need to cast anything…


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x