Saltar al contenido

Automapper creando una nueva instancia en lugar de propiedades de mapa

Después de mucho trabajar ya hallamos el resultado de esta traba que muchos de nuestros lectores de nuestra web han presentado. Si deseas aportar algo no dudes en aportar tu conocimiento.

Solución:

Esta es una limitación de AutoMapper hasta donde yo sé. Es útil tener en cuenta que, si bien la biblioteca se usa popularmente para mapear a/desde ver modelos y entidades, es una biblioteca genérica para mapear cualquier clase a cualquier otra clase y, como tal, no tiene en cuenta todas las excentricidades de un ORM como Entity Framework.

Entonces, aquí está la explicación de lo que está sucediendo. Cuando asigna una colección a otra colección con AutoMapper, literalmente está asignando la recopilación, no los valores de los elementos de esa colección a los elementos de una colección similar. En retrospectiva, esto tiene sentido porque AutoMapper no tiene una forma confiable e independiente de determinar cómo debe alinear un elemento individual en una colección con otro: ¿por id? ¿Qué propiedad es el id? tal vez los nombres deberían coincidir?

Entonces, lo que sucede es que la colección original de su entidad se reemplaza por completo con una colección completamente nueva compuesta por instancias de elementos completamente nuevos. En muchas situaciones, esto no sería un problema, pero cuando combina eso con el seguimiento de cambios en Entity Framework, ahora indica que toda la colección original debe eliminarse y reemplazarse con un nuevo conjunto de entidades. Obviamente, eso no es lo que quieres.

Entonces, ¿cómo resolver esto? Bueno, desafortunadamente, es un poco doloroso. El primer paso es decirle a AutoMapper que ignore la colección por completo al mapear:

Mapper.CreateMap();
Mapper.CreateMap()
    .ForMember(dest => dest.UserPreferences, opts => opts.Ignore());

Tenga en cuenta que dividí esto en dos mapas. No necesita ignorar la colección al mapear a su modelo de vista. Eso no causará ningún problema porque EF no está rastreando eso. Solo importa cuando está mapeando de nuevo a su clase de entidad.

Pero, ahora que no está mapeando esa colección en absoluto, entonces, ¿cómo vuelve a poner los valores en los elementos? Desafortunadamente, es un proceso manual:

foreach (var pref in model.UserPreferences)

    var existingPref = user.UserPreferences.SingleOrDefault(m => m.Id == pref.Id);
    if (existingPref == null) // new item
    
        user.UserPreferences.Add(Mapper.Map(pref));
    
    else // existing item
    
        Mapper.Map(pref, existingPref);
    

Mientras tanto, existe una extensión AutoMapper para ese problema en particular:

cfg.AddCollectionMappers();
cfg.CreateMap().EqualityComparison((s, d) => s.ID == d.ID);

Con AutoMapper.EF6/EFCore también puede generar automáticamente todas las comparaciones de igualdad. Consulte AutoMapper.Collection AutoMapper.EF6 o AutoMapper.Collection.EFCore

De acuerdo con el archivo fuente de AutoMapper que maneja todo ICollection (entre otras cosas) y el ICollection Mapper:

El cobro se borra mediante una llamada a Clear() luego se agregó nuevamente, por lo que puedo ver, no hay forma de que AutoMapper pueda hacer el mapeo automáticamente esta vez.

Implementaría alguna lógica para recorrer las colecciones y AutoMapper.Map los que son iguales

Reseñas y calificaciones

Recuerda dar recomendación a este artículo si si solucionó tu problema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *