Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expression mapping fails on one specific machine. #2612

Closed
Baune8D opened this issue Apr 23, 2018 · 15 comments
Closed

Expression mapping fails on one specific machine. #2612

Baune8D opened this issue Apr 23, 2018 · 15 comments

Comments

@Baune8D
Copy link

Baune8D commented Apr 23, 2018

Source/destination types

protected async Task<TEntity> GetEntityByDtoAsync(TDto dto)
{
    var mappedExpression = _mapper.Map(dto, typeof(TDto), typeof(Expression<Func<TEntity, bool>>));
    if (!(mappedExpression is Expression<Func<TEntity, bool>> equivExpr)) return null;
    return await DbSet.SingleOrDefaultAsync(equivExpr);
}

Mapping configuration

public static void ConfigureAutoMapper(this IServiceCollection services, Assembly assemblyToScan = null)
{
    var mappingAssembly = typeof(UserProfile).Assembly;

    services.AddAutoMapper(cfg =>
    {
        if (assemblyToScan != null)
        {
            cfg.AddProfiles(mappingAssembly, assemblyToScan);
        }
        else
        {
            cfg.AddProfiles(mappingAssembly);
        }
        cfg.AddCollectionMappers();
        cfg.SetGeneratePropertyMaps<GenerateEntityFrameworkPrimaryKeyPropertyMaps<CustomDbContext>>();
    });
}

Version: x.y.z

AutoMapper v6.2.2
AutoMapper.Collection v3.1.3
AutoMapper.Collection.EntityFramework v3.1.3
AutoMapper.EF6 v1.1.1
AutoMapper.Extensions.Microsoft.DependencyInjection v3.2.0

Application is a ASP.NET Core 2.0 web app using .NET Framework 4.7.1

Expected behavior

var mappedExpression = _mapper.Map(dto, typeof(TDto), typeof(Expression<Func<TEntity, bool>>));

This line works perfectly fine on my development machine. (Windows 10)

Actual behavior

Same line fails on our test server (Windows Server 2012 R2).
It fails with the following exception:

An unhandled exception occurred while processing the request.
AutoMapperConfigurationException: 
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
=====================================================================================================================================================================================================================================================================================================================================================================================
ConversationDto -> Expression`1 (Destination member list)
Organization.Domain.DTOs.ConversationDto -> System.Linq.Expressions.Expression`1[[System.Func`2[[Organization.CodeFirst.Models.Conversation, Organization.CodeFirst, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] (Destination member list)

Unmapped properties:
Parameters
No available constructor.
AutoMapper.ConfigurationValidator.AssertConfigurationIsValid(IEnumerable<TypeMap> typeMaps)

Steps to reproduce

I cannot reproduce this as it only happens on our test server. I have tried using the exact same application produced with 'dotnet publish' and it works fine on one machine but fails on another.
I am completely lost and have spent days on this problem. Is there anything in AutoMapper that could be dependent on something OS specific?

@lbargaoanu
Copy link
Member

You need to isolate the issue. You shouldn't call AssertConfigurationIsValid in production. Its purpose is to help during development.

@Baune8D
Copy link
Author

Baune8D commented Apr 23, 2018

@lbargaoanu I dont call Assert. App crashes with the exception at the _mapper.Map line as described above. The Assert happens inside AutoMapper.

@lbargaoanu
Copy link
Member

lbargaoanu commented Apr 23, 2018

But that means you have a dynamic map. That doesn't make any sense. Maybe you do have a map and it's not found?

@Baune8D
Copy link
Author

Baune8D commented Apr 23, 2018

@lbargaoanu I would really like to isolate the problem but it works perfectly fine in my development machine but crashes when moving the exact same source files to another machine.

@Baune8D
Copy link
Author

Baune8D commented Apr 23, 2018

@lbargaoanu I have a map setup like this

CreateMap<ConversationDto, Conversation>();

@lbargaoanu
Copy link
Member

I think this is better suited for StackOverflow. Get back to us if the problem is with AM itself, but it doesn't look that way to me.

@Baune8D
Copy link
Author

Baune8D commented Apr 23, 2018

@lbargaoanu I have a remote debugger attached to the other faulting server and i can see it has loaded all the mapping profiles.

Is there anything you can think off that could help me debug this problem? The error is thrown inside AutoMapper itself. I am using the exact same published source code on both machines, i am running them in the same ASPNETCORE_ENVIRONMENT and against the same database. But the error only happens on that one machine.

You say that it should only run Assert if it tries to use a dynamic map? That is a clue i can go aftern.
Do you have any other clues off the top of your head?

@lbargaoanu
Copy link
Member

Check the execution plan.

@Baune8D
Copy link
Author

Baune8D commented Apr 23, 2018

@lbargaoanu I just fetched an executionplan from both the working machine and the non-working machine.

The working machine:

(source, mapperDestination, context) => (source == null)
    ? (mapperDestination == null) ? null : mapperDestination
    : {
        try
        {
            return ObjectToEquivalencyExpressionByEquivalencyExistingMapper.Map(source, EquivalentExpression<ConversationDto, Conversation>);
        }
        catch (Exception ex)
        {
            throw new AutoMapperMappingException("Error mapping types.", ex, AutoMapper.TypePair);

            return null;
        }
    }

The non-working machine:

(src, dest, ctxt) =>
{
    Expression<Func<Conversation, bool>> typeMapDestination;
    return (src == null)
        ? null
        : {
            ctxt.ValidateMap(TypeMap);
            typeMapDestination = dest ?? 
            {
                throw ArgumentException;

                return null;
            };

            return typeMapDestination;
        };
}

Obviously something is different?

@lbargaoanu
Copy link
Member

lbargaoanu commented Apr 23, 2018

Yes, and that's a dynamic map, as the exception says. How is that supposed to work, I have no idea :) If you set CreateMissingTypeMaps to false, it will tell you you're missing a map.

@Baune8D
Copy link
Author

Baune8D commented Apr 25, 2018

@lbargaoanu I just wanted to let you know that i resolved the problem and you were right, it was not an AutoMapper error.

AutoMapper instantiated a version of my DbContext with a wrong connection string which made AutoMapper not able to access the DbContext on the faulting server.

The error happend here:
https://github.com/AutoMapper/AutoMapper.Collection/blob/master/src/AutoMapper.Collection.EntityFramework/GenerateEntityFrameworkPrimaryKeyPropertyMatches.cs#L24
as _context.ObjectContext threw an exception because of the wrong connection string.

Maybe a check for an invalid context could be made here and a relevant error message shown. It was extremely difficult to track down this error in the current state.

@lbargaoanu
Copy link
Member

Yes, but the thing is, this repo is for the core package only. So really you know a lot more than me about all those extra packages you use :) I'm not saying it's easy to isolate the issue, but it's kind of your job to do it. The people responsible for those higher level packages might be able to help too.

@Baune8D
Copy link
Author

Baune8D commented Apr 25, 2018

@lbargaoanu Oh yeah forgot that this is the AutoMapper repo. I will put up an issue in AutoMapper.Collection instead about handling of the error :)

Thanks for all your help anyways, very appreciated :)

@lbargaoanu
Copy link
Member

:)

@lock
Copy link

lock bot commented May 6, 2019

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.

@lock lock bot locked as resolved and limited conversation to collaborators May 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants