LINQ and AutoMapper
You're operating on IQueryable
, which tries to translate the method you supply into SQL. Obviously, it's not going to happen, as you're passing AutoMapper related magic. There's an easy solution, you have to force execution before mapping:
return roles.ToList().Select(role => Mapper.Map<Role, RoleDto>(role)).ToList();
[EDIT] As Daniel suggests in comments, you can always go from IQueryable
to IEnumerable
by calling AsEnumerable()
and still defer execution:
return roles.AsEnumerable().Select(role => Mapper.Map<Role, RoleDto>(role)).ToList();
Comments
-
Jammer over 4 years
I'm wondering if there is anything I can do to get this working as expected. This works fine in my code:
var roles = _securityContext.Set<Role>(); var roleList = new List<RoleDto>(); foreach (var role in roles) { roleList.Add(Mapper.Map<Role, RoleDto>(role)); } return roleList;
But changing this to:
var roles = _securityContext.Set<Role>(); return roles.Select(role => Mapper.Map<Role, RoleDto>(role)).ToList();
Results in an error I've not seen before:
"LINQ to Entities does not recognize the method 'Security.Dto.RoleDto MapRole,RoleDto' method, and this method cannot be translated into a store expression"
I'm not sure if I can even do anything about this'problem' ... arguably the method that works is more readable anyway ...
-
Daniel Hilgarth over 11 yearsUsing
AsEnumerable()
instead ofToList()
is better as it still will perform deferred execution. -
Aniket Inge over 11 yearsThat has to be the funniest name I've come across online!
-
Patryk Ćwiek over 11 years@Jammer But be careful when and where you dispose of the context. If you dispose the
DbContext
before materializing the collection (by e.g. callingToList()
, you'll getObjectDisposedException
when trying to do anything with the result. -
Jammer about 11 years@Trustme-I'maDoctor for sure. I generally keep the same context around for the duration of a request and then dispose of it so I shouldn't see this exception! ... famous last words! Thanks!
-
CodeMonkeyKing over 10 yearsThe Edit above says that execution is deferred, however, the the ToList() contradicts that. If deferred execution is desired, then the ToList() should be removed and the result returned should be IEnumerable<RoleDto>.
-
Patryk Ćwiek over 10 years@CodeMonkeyKing
AsEnumerable
would move it to LINQ to Objects domain and defer execution until the lastToList()
, while the first example creates two lists one after another. That's the difference. :)