AutoMapper / AutoMapper.Collection.EFCore

EFCore support for AutoMapper.Collections
MIT License
139 stars 21 forks source link

Missing type map configuration or unsupported mapping #30

Closed cursorme closed 3 years ago

cursorme commented 4 years ago

Hi,

I'm getting this error:

"AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping. PipetteModelDto -> Expression1 PipetteModels.PipetteModelDto -> System.Linq.Expressions.Expression1[[System.Func`2[[VolumetricsDomain.PipetteModel, VolumetricsDomain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, ..."

Seems that when tring to make: await _context.PipetteModels.Persist (_mapper).InsertOrUpdateAsync(PipetteModelDto);

Is expecting a map to a expression and not something line I have rigth now: CreateMap<PipetteModel, PipetteModelDto> () ... .ReverseMap ();

On startup I have: services.AddAutoMapper ((serviceProvider, automapper) => { automapper.AddProfile(new MappingProfile()); automapper.AddCollectionMappers (); automapper.UseEntityFrameworkCoreModel (serviceProvider); automapper.SetGeneratePropertyMaps<GenerateEntityFrameworkCorePrimaryKeyPropertyMaps>(); }, typeof (DataContext).Assembly);

What would be the correct mapping to use from a dto to a EF Core class ?

Thanks Eduardo

Tasteful commented 4 years ago

Start with removing the automapper.SetGeneratePropertyMaps<GenerateEntityFrameworkCorePrimaryKeyPropertyMaps>(); line, it should not be there, the UseEntityFrameworkCoreModel<> will set the correct property maps up for you.

Please, provide more information about your model and dto's and if possible small complete example that will cause this exception.

cursorme commented 4 years ago

Hi,

Removing that line the error is exacly the same.I've use it because I've found it here as alternative to use EqualityComparison for each entity.... I'm a lazy guy :) I will try to gather a more complete sample to show it but seems that could be related to this ? "Note: This is done by converting the OrderDTO to Expression<Func<Order,bool>> and using that to find matching type in the database."

"Normal" automapper Map works fine. For example the first line works properly while the commented one does not throwing that error: var test = _mapper.Map<PipetteModelDto, PipetteModel> (request.PipetteModel); //await _context.PipetteModels.Persist (_mapper).InsertOrUpdateAsync(request.PipetteModel);

I'm using .Net Core 3.1 + EF Core + Npgsql 3.1 + Automapper 9.0 I've just open is issue to see if I was missing something pretty obvious or not....

Thanks Eduardo

rdkashmir commented 4 years ago

I am facing the same error.

Tasteful commented 4 years ago

@rdkashmir Please, provide more information about your model and dto's and if possible small complete example that will cause this exception.

rdkashmir commented 4 years ago

Hi, thanks for your time to get more information about the things.

I was missing a mapping for one table which was causing the issue. I fixed it and it worked like charm.

On Mon, 27 Apr 2020, 12:04 pm Patric Forsgard, notifications@github.com wrote:

@rdkashmir https://github.com/rdkashmir Please, provide more information about your model and dto's and if possible small complete example that will cause this exception.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AutoMapper/AutoMapper.Collection.EFCore/issues/30#issuecomment-619759283, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALRPISDZVHLRRLE7VNBOOSTROURN7ANCNFSM4KHEV5GQ .

AccessViolator commented 4 years ago

I get this error when I pass a db entity rather than a dto to InsertOrUpdate(). A very disappointing limitation.

themisir commented 4 years ago

I fixed this issue by not using AutoMapper.Collections.EntityFrameworkCore and adding a few rules to mapper profile.

CreateMap<Category, CategoryDto>()
    .EqualityComparison((a, b) => a.Id == b.Id);

CreateMap<CategoryDto, Category>()
    // REQUIRED to ignore primary keys
    .ForMember(x => x.Id, x => x.Ignore())
    .EqualityComparison((a, b) => a.Id == b.Id);

CreateMap<CategoryTranslation, CategoryTranslationDto>()
    .EqualityComparison((a, b) => a.LanguageId == b.LanguageId);

CreateMap<CategoryTranslationDto, CategoryTranslation>()
    .EqualityComparison((a, b) => a.LanguageId == b.LanguageId);

Instead of Collections.EFCore you could write something like that:

// Received from request body ([FromBody] CategoryDto doc)
CategoryDto dto;

// Update data
Category model = await _context.Categories
    .Include(c => c.Translations)
    .SingleOrDefaultAsync(c => c.Id == id);

if (model == null) {
    return NotFound();
}

_mapper.Map(dto, model);
await _context.SaveChangesAsync();

// Add new entry
Category model = _mapper.Map<Category>(dto);

_context.Categories.Add(model);
await _context.SaveChangesAsync();

I know it's not same thing as InsertOrUpdate but I think most of the times we need to just insert or update data.

iimadao commented 4 years ago

me too , but yes .Persist(mapper).InsertOrUpdateAsync(parms); @### ### ::><::

felaray commented 4 years ago

I have same problem for remove data. await _context.AppUser.Persist(mapper).RemoveAsync(result);

WebAPI code

    public async Task<IActionResult> UpdateUser(AppUserDTO model)
    {
        try
        {

            var data = await _context.AppUser.Include(c => c.Logs).AsNoTracking().SingleOrDefaultAsync(c => c.Id == model.Id);

            if (data == null)
                return NotFound();

            var mapper = new MapperConfiguration(cfg =>
            {
                cfg.AddCollectionMappers();
                cfg.CreateMap<AppUserDTO, AppUser>()
                .EqualityComparison((odto, o) => odto.Id == o.Id);

                cfg.CreateMap<LogDTO, Log>()
                .EqualityComparison((odto, o) => odto.Id == o.Id);

            }).CreateMapper();
            var result = mapper.Map<AppUserDTO, AppUser>(model, data);

            await _context.AppUser.Persist(mapper).InsertOrUpdateAsync(model);

            //Remark it and worked
            await _context.AppUser.Persist(mapper).RemoveAsync(result);

            data = await _context.AppUser.Include(c => c.Logs)
                .AsNoTracking()
               .SingleOrDefaultAsync(c => c.Id == model.Id);

            return Ok(data);
        }
        catch (Exception ex)
        {

            return BadRequest(ex.InnerException == null ? ex.Message : ex.InnerException.Message);
        }
    }

public class AppUser : IdentityUser<int>
{
    public List<Log> Logs { get; set; }
}

public class Log
{
    public int AppUserId { get; set; }
    public int Id { get; set; }
    public string Msg { get; set; }
}

public class AppUserDTO
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public List<Log> Logs { get; set; }
}

public class LogDTO : Log
{
}

Error message:

**Missing type map configuration or unsupported mapping.

Mapping types: AppUser -> Expression1 AutoMapperForEFcore.Models.AppUser -> System.Linq.Expressions.Expression`1[[System.Func2[[AutoMapperForEFcore.Models.AppUser, AutoMapperForEFcore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]**

AutoMapper 9.0.0 AutoMapper.Collection 6.0.0 AutoMapper.Collection.EntityFrameworkCore 1.0.1

Tasteful commented 4 years ago

@felaray you are not initiating this package in the mapping configuration. See configuration example in the readme.

Tasteful commented 4 years ago

The '**Missing type map configuration or unsupported mapping.' Is from automapper that changed a default settings, see their breaking changes.

felaray commented 4 years ago

It's my mistake, the problem has been solved , thanks!

MehrajShakil commented 1 year ago
var user =_userRepository.GetUserByUsernameAsync(username);
if (user is null) return NotFound();
_ = _mapper.Map(memberUpdateDto, user);

I've also faced the same issue. After a while I realize that I forget to use await when query into database.
When I fix it ,

var user = await _userRepository.GetUserByUsernameAsync(username);

Then, It works fine.

dainq94 commented 9 months ago

Thank you, It works for me @MehrajShakil