.net-coreautomapperautomapper-8

Best way to create a map between two entities with a third one from another context


Hi I'd like to create a map between two entities (source: User, target: UserInfosDto) while one member of the target DTO (UserItemPreference) needs info from a third entity inside another context.

public class UserInfosDto
{
    //public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }

    public UserItemPreferencesDto UserItemPreferences { get; set; }
}
public class UserItemPreferencesDto
{
    public bool SeeActuality { get; set; }
    public bool IsInEditorMode { get; set; }
}
public class User
{
    public string IdentityId { get; set; }
    //...
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

public class UserIdentity
{
    public string IdentityId { get; set; }
    //...  
    public bool SeeActuality { get; set; }
    public bool IsInEditorMode { get; set; }  
}

User and UserIdentity come from different databases but have a common property IdentityId. I thought about using ITypeConverter in which I would inject the UserIdentity dbContext. Problem is that I can't find a way to use ITypeConverter on one member only.


Solution

  • Use an IValueResolver instead, which allows to resolve separate members instead of full types.

    For your case above it will look like

    public class UserItemPreferencesResolver
        : IValueResolver<User, UserInfosDto, UserItemPreferencesDto>
    {
        private readonly UserEntityDbContext _dbContext;
    
        public UserItemPreferencesResolver(UserEntityDbContext dbContext)
        {
            _dbContext = dbContext;
        }
    
        public UserItemPreferencesDto Resolve(
            User source,
            UserInfosDto destination,
            UserItemPreferencesDto destinationMember,
            ResolutionContext context
            )
        {
            UserItemPreferencesDto preferences = /* resolve from _dbContext (and transform) */
            return preferences;
        }
    }
    

    Your create the mapping via

    CreateMap<User, UserInfosDto>()
        .ForMember(
            dest => dest.UserItemPreferences, 
            opt => opt.MapFrom<UserItemPreferencesResolver>()
        );