I am using AutoMapper 4.2.1.0 to map an entity type into a DTO using ProjectTo .
I have created my Map like this :
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Order, OrderDTO>();
cfg.CreateMap<Order_Detail, Order_DetailDTO>();
});
and I am using config object like this :
var builder = config.ExpressionBuilder;
return ((IQueryable<Order>) property.GetValue(_db, null)).ProjectTo<OrderDTO>(builder);
but I am getting an error that says :
Missing map from Order to OrderDTO. Create using Mapper.CreateMap
.
Is there something that I do wrong ?
Here is the same question that I asked on SO:
http://stackoverflow.com/questions/36450885/automapper-doesnt-work-as-it-should
var ((IQueryable<TEntity>) property.GetValue(_db, null)).ProjectTo<TDto>(config); should work
I was misled by this article :
https://lostechies.com/jimmybogard/2016/01/21/removing-the-static-api-from-automapper/
Interesting, I found that this ONLY works if you give the ProjectTo
Also IMapperConfiguration appears to be missing the method "CreateMapper" is that by design?
@TehWardy There's another overload to pass IMapperConfiguration and only that. The static API is back so you use a static instance you don't have to pass over IMapperConfiguration.
And yes CreateMapper no longer shows up in Static or IMapperConfiguration by design. Creating maps at any point in time after initialization causes issues with order and map inheritance, so you have to do them all at once.
When I do this I get an exception ...
There's another overload to pass IMapperConfiguration and only that.
This makes sense but it's not what i'm trying to do ...
Creating maps at any point in time after initialization causes issues with order and map inheritance
For example:
In my situation I am using Ninject as my IoC container in to the object that has the various methods I want to call. In this case my methods are various CRUD operations on an IQueryable
now lets assume I have the following ...
A ninject module:
public class AutoMapperNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMapperConfiguration>().ToMethod(k => new MapperConfiguration(cfg =>
{
var profiles = TypeHelper.GetWebStackAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.BaseType == typeof(Profile))
.ToList();
profiles.ForEach(p => cfg.AddProfile(Activator.CreateInstance(p, null) as Profile));
})).InSingletonScope();
Bind<IMapper>().ToMethod(k => ((MapperConfiguration)k.Kernel.Get<IMapperConfiguration>()).CreateMapper()).InSingletonScope();
}
}
And then in my class I pass these in as Ctor args ...
IMapper mapper;
IMapperConfiguration mapperConfig;
When querying the db ...
var result = db.GetAll().ProjectTo<TDto>(mapperConfig);
... this for me this does not work without casting mapperConfig to the concrete type "MapperConfiguration" first.
I also cannot give the same ProjectTo call the IMapper I have for some reason (i would prefer to only ever pass around an IMapper instance).
In a creation scenario I appear to be getting similar problems, for example ...
var mappedDto = mapper.Map<TEntity>(data);
var savedEntity = await service.AddAsync(mappedDto);
var result = mapper.Map<TDto>(savedEntity);
... this for me has been picked up as a testing fail by my QA team, and upon further testing I can confirm the same problem.
Whereas the same init code used with a static mapper works fine.
Do I have use different overloads with the new non static versions to what I was using with the old static versions?
The IMapper vs IMapperConfiguration for ProjectTo was @jbogard code. I thought it was confusing too.
There shouldn't be any special overrides other than what's defined in the documentation. I'm not familiar with NInject, so I don't know if that might be the problem.
My suggestion is if you can, go back to the static implementation using
Mapper.Initialize(cfg =>
{
var profiles = TypeHelper.GetWebStackAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.BaseType == typeof(Profile))
.ToList();
profiles.ForEach(p => cfg.AddProfile(Activator.CreateInstance(p, null) as Profile));
});
and just call Mapper.Map
Ok looking at the tests defined here:
It looks like projectTo also supports passing a MapperConfiguration param to it to use with the Projection.
In testing I managed to get this to behave :)
thx @jbogard
@jbogard It's probably worth noting that for "good coding practice" the API mentioned in my last comment should probably accept a IMapperConfig or an IMapper instead if that's possible instead of requiring the concrete types ... it would likely promote better forward compatibility.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
var ((IQueryable<TEntity>) property.GetValue(_db, null)).ProjectTo<TDto>(config);should work