Closed ComtelJeremy closed 3 years ago
Hi @ComtelJeremy,
That is strange. There is a call to CreateMapper().Map(dto, entity)
which has to be fundamental methods in AutoMapper.
I'll have a look, but I'm very busy so it won't be for a week or more.
PS. Please let me know which version of EfCore.GenericServices you are using.
Note to self. The AutoMapper 10.0 upgrade guide talks about a change to Context.Mapper.Map
. I don't use that but it sounds like that effects the code _wrappedMapper.MapperSaveConfig.CreateMapper().Map(dto, entity);
in the class CreateMapper
.
Hi @JonPSmith ,
I'm using 3.2.2, if that helps.
I just updated version 3.2.2 to latest AutoMapper and all the tests works. Clearly there is a problem I I need more info.
I think you will have to provide a complete console app containing your problem and I will have a look.
Hi @ComtelJeremy,
I haven't heard anything back and I can't fix it without some code from you that shows the problem. Therefore I'm closing this issue.
@JonPSmith,
Sorry for the delay, and thanks for reminding me... We've been busy here rolling out our new release, and I didn't have a chance to try to repro it once I worked around it.
I can't recreate it now. My previous fix was simply to roll back AutoMapper, and all was good. But now when I update AutoMapper back (and expected it to cause the issue again) it doesn't throw... So strange, as nothing else changed. I even reverted to the commit where we had the issue, and no dice.
Since that issue I have cleared my local Visual Studio nuget cache (to fix a global tool), so the only thing I can think of was that I didn't have the updated AutoMapper (the nuget cache was off or something) and that's why it threw. In any case, if it ever shows up again and I can repro it, I'll let you know.
Sorry for the bother.
Jeremy
Hi @ComtelJeremy,
No problem. Glad its sorted.
PS. One possible explanation is you had different AutoMapper versions across your projects.
Hi Jon (@JonPSmith),
FYI, this bit us again, this time it made it (due to some missed testing by us) to our Staging and Production (which is built using dev ops - so I know it isn't a nuget cache issue). It again seems to be limited to CreateAndSaveAsync. In this release we updated AutoMapper from 9.0.0 to the latest (10.1.1). It only seems to affect CreateAndSave and only when a dto is passed, not an entity class, so we missed it in testing.
I narrowed it down to this line: https://github.com/JonPSmith/EfCore.GenericServices/blob/0e7e7e50a69124b77ceaecc79e8bd2cc75853594/GenericServices/Internal/MappingCode/CreateMapper.cs#L71
it throws this:
System.MissingMethodException: Method not found: '!!1 AutoMapper.IMapper.Map(!!0, !!1)'.
at GenericServices.Internal.MappingCode.CreateMapper+GenericMapper<TDto, TEntity>.MapDtoToEntity(TDto dto, object entity)
at CallSite.Target(Closure , CallSite , object , ProjectCreateDto , object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3<T0, T1, T2>(CallSite site, T0 arg0, T1 arg1, T2 arg2)
at GenericServices.Internal.MappingCode.EntityCreateHandler<TDto>.CreateEntityAndFillFromDto(TDto dto, string methodCtorName)
at GenericServices.PublicButHidden.CrudServicesAsync<TContext>+<CreateAndSaveAsync>d__9<T>.MoveNext()
It appears that this is the case because there is no overload in Automapper that I could see that supports a typed dto with an object (boxed) entity as shown here: https://github.com/AutoMapper/AutoMapper/blob/bdc0120497d192a2741183415543f6119f50a982/src/AutoMapper/Mapper.cs#L156-L170
public TDestination Map<TDestination>(object source) => Map(source, default(TDestination));
public TDestination Map<TDestination>(object source, Action<IMappingOperationOptions<object, TDestination>> opts) => Map(source, default, opts);
public TDestination Map<TSource, TDestination>(TSource source) => Map(source, default(TDestination));
public TDestination Map<TSource, TDestination>(TSource source, Action<IMappingOperationOptions<TSource, TDestination>> opts) =>
Map(source, default, opts);
public TDestination Map<TSource, TDestination>(TSource source, TDestination destination) =>
MapCore(source, destination, DefaultContext);
public TDestination Map<TSource, TDestination>(TSource source, TDestination destination, Action<IMappingOperationOptions<TSource, TDestination>> opts) =>
MapWithOptions(source, destination, opts);
public object Map(object source, Type sourceType, Type destinationType) => Map(source, null, sourceType, destinationType);
public object Map(object source, Type sourceType, Type destinationType, Action<IObjectMappingOperationOptions> opts) =>
Map(source, null, sourceType, destinationType, opts);
public object Map(object source, object destination, Type sourceType, Type destinationType) =>
MapCore(source, destination, DefaultContext, sourceType, destinationType);
public object Map(object source, object destination, Type sourceType, Type destinationType, Action<IObjectMappingOperationOptions> opts) =>
It seems to be an issue since you pass in an entity of type object, not the specific entity type (or use a generic overload). Is it possible for you to use a typed overload?
I can recreate the issue locally if you need me to try something. I have checked and all of the references to AutoMapper are to the latest across all our projects, and the Automapper.dll in the bin\debug is 10.1.1.
This shows up when we call CreateAndSaveAsync passing in a dto. If we pass in the entity type itself, this is not an issue and no error is thrown. I assume it calls a different method, as no mapping is needed?
For now we are manually mapping anywhere there is a dto... Fortunately there aren't too many maps to change, but it would be nice to get it auto-mapping again.
Hi @ComtelJeremy,
OK, I'm busy at the moment so it won't be a quick reply.
One question: are you using the version 3.2.2 or the 5.0.0?
Hi @JonPSmith, we are using 3.2.2, as we have not moved to NET 5 yet.
Hi @ComtelJeremy,
I had a look at it and its a weird bug when an new version of AutoMapper overrides a old version of AutoMapper. This is confirmed by Version 5.0.0 which uses AutoMapper 10.1.1 with not problem. If the unit test had AutoMapper 10.1.1 and GenericServices had AutoMapper 9.0.0 it fails. If both have AutoMapper 10.1.1 it works.
I have released version 3.3.0 using AutoMapper 10.1.1. Please check this works for you.
@JonPSmith Thank you for checking it out. We will try it shortly.
@JonPSmith, this fixes the issue! Thank you again. And just in time... since your comment and release we had one other area where this showed up in Production, and the 3.3.0 corrected it with no other code changes! 👍🏻
Hello Jon,
I received the following stack trace when I have AutoMapper 10.1.1 installed (latest).
I think it would be at this line in your code.
Apparently there is a missing method in the new version of AutoMapper, it seems specifically in the Mapper class. Maybe somewhere around here??? Rolling back to 9.0.0 seemed to fix it. Is there anything that can be done in the library here to allow it to work with either version? Or is there something else I am missing that would allow us to use the latest AutoMapper?
Thank you for your insights,
Jeremy