Reputation: 1368
I have the following entities and corresponding view models
public class TopEntity
{
public int Id { get; set; }
public ICollection<BottomEntity> Bottoms { get; set; }
}
public class BottomEntity
{
public int Id { get; set; }
public int TopId { get; set; }
}
public class TopEntityViewModel
{
public int Id { get; set; }
public ICollection<BottomEntityViewModel> Bottoms { get; set; }
}
public class BottomEntityViewModel
{
public int Id { get; set; }
}
I want to map an instance of type TopEntityViewModel
to an instance of type TopEntity
without overriding any value on BottomEntity.TopId
that might already be there.
I've configured AutoMapper as follows:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore());
});
I've added .ForMember(dest => dest.TopId, opts => opts.Ignore());
to ignore BottomEntity.TopId
during mapping thinking that it should help preserve the existing value.
I'm mapping the instances like so:
mapperConfig.AssertConfigurationIsValid();
var mapper = mapperConfig.CreateMapper();
var topEntity = new TopEntity
{
Id = 45,
Bottoms = new List<BottomEntity>
{
new BottomEntity
{
Id = 56,
TopId = 45
},
new BottomEntity
{
Id = 57,
TopId = 45
}
}
};
var topEntityVm = new TopEntityViewModel
{
Id = 45,
Bottoms = new List<BottomEntityViewModel>
{
new BottomEntityViewModel
{
Id = 56,
},
new BottomEntityViewModel
{
Id = 57
}
}
};
var updatedTopEntity = mapper.Map(topEntityVm, topEntity);
When I access updatedTopEntity.Bottoms[<whatever>].TopId
it's always set to 0.
If I update my definition of the property BottomEntity.TopId
on the class to have a default value like 1000
, after mapping all my updatedTopEntity.Bottoms[<whatever>].TopId
are set to that default value (1000
in the example).
I've checked if the references returned from mapper.Map
map the original references and they do.
How do I prevent AutoMapper from removing any existing values on the existing instances ?
I'm using AutoMapper 10.1.1 with .NET Core 5. You can try a working example here.
Upvotes: 1
Views: 3283
Reputation: 1368
AutoMapper
says this in the documentation:
When mapping to an existing collection, the destination collection is cleared first. If this is not what you want, take a look at AutoMapper.Collection.
AutoMapper.Collection, according to the documentation, does:
Adds ability to map collections to existing collections without re-creating the collection object.
Will Add/Update/Delete items from a preexisting collection object based on user defined equivalency between the collection's generic item type from the source collection and the destination collection.
After installing AutoMapper.Collection
I've updated the AutoMapper configuration as follows:
var mapperConfig = new MapperConfiguration(exp =>
{
exp.AddCollectionMappers();
exp.CreateMap<TopEntity, TopEntityViewModel>();
exp.CreateMap<BottomEntity, BottomEntityViewModel>();
exp.CreateMap<TopEntityViewModel, TopEntity>();
exp.CreateMap<BottomEntityViewModel, BottomEntity>()
.ForMember(dest => dest.TopId, opts => opts.Ignore())
.EqualityComparison((src, dest) => src.Id == dest.Id);
});
The line .EqualityComparison((src, dest) => src.Id == dest.Id);
adds an equality comparison that AutoMapper will use as follows:
This behavior of AutoMapper.Collection
is described here
Working example: https://dotnetfiddle.net/tnaUjY
Thanks to Lucian Bargaoanu for pointing me to the correct direction
Upvotes: 4