Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve - unable to cast Generic.List to Linq.IQueryable using Automapper?

I'm getting the following error in using a DTO and EF model:

Unable to cast object of type 'System.Collections.Generic.List1[Project.Core.UI.Models.ContentTypes]' to type 'System.Linq.IQueryable1[Project.Core.UI.Models.ContentTypes]

Bootstrapped: Mapper.CreateMap<ContentType, Project.Core.UI.Models.ContentTypes>();

In an OData controller method public IQueryable<ContentTypes> Get() {...}, using:

var result = Mapper.Map<IQueryable<ContentType>, IQueryable<ContentTypes>>(_repository.Query().Get()
    .Where(u => u.UserId == userId)
    .OrderBy(o => o.Description));

I have also tried the following but I suspect that this is exactly what the above is as well:

var result =_repository.Query().Get()
    .Where(u => u.UserId == userId)
    .OrderBy(o => o.Description);
var dto = Mapper.Map<IQueryable<ContentType>, IQueryable<ContentTypes>>(result);
return dto;

How can I create the appropriate mapping for this?

like image 317
ElHaix Avatar asked Feb 08 '14 15:02

ElHaix


3 Answers

You need to be aware of the fact that by creating your mapping in such a way:

Mapper.CreateMap<ContentType, Project.Core.UI.Models.ContentTypes>();

Only these basic generic collection types are supported implicitly:

IEnumerable
IEnumerable<T>
ICollection
ICollection<T>
IList
IList<T>
List<T>
Arrays

But not IQueryable<T>. That's why you get the exception.

Therefore you should try doing sth like this:

var dto = Mapper.Map
         <IEnumerable<ContentType>, 
          IEnumerable<ContentTypes>>(result.AsEnumerable()); 
// or e.g. List/List/ToList()
like image 72
Paweł Bejger Avatar answered Nov 02 '22 08:11

Paweł Bejger


In addition to what bejger said you can also use the QueryableExtensions namespace in Automapper to map IQueryable objects, but it puts some limitations on what setup you can do between two object when you do your CreateMap<TSource, TDest>

instead of using it like

IQueryable<ContentTypes> dto = Mapper.Map<IQueryable<ContentType>, IQueryable<ContentTypes>>(result);

you instead use it like

IQueryable<ContentTypes> dto = result.Project().To<ContentTypes>();
like image 2
Scott Chamberlain Avatar answered Nov 02 '22 07:11

Scott Chamberlain


You can use the 'ProjectTo' method instead.

var result = iQueryableResultSet.ProjectTo<MyObjectName>(_mapper.ConfigurationProvider);

Optionally you pass the ConfigurationProvider from any injected Mapper instance, as necessary.

like image 2
Ian Avatar answered Nov 02 '22 08:11

Ian