1

I have a problem when mapping collections with Automapper 6 and I can't find a solution. In the updatedArticle object below I have the old Created and Updated values left after mapping since they do not exist on the view model. However the values for Created and Updated in Descriptions are lost. The values that do come in via the view model are all updated correctly. What am I doing wrong? Automapper also loses Entity Framework 6 mapping for Article since those values are lost as well.

Controller method:

public async Task<IHttpActionResult> UpdateArticle(ArticleViewModel articleVm)
{
    Article articleOriginal = await iArticleRepository.GetAsync(articleVm.Id);
    Article updatedArticle = Mapper.Map<ArticleViewModel, Article>(articleVm, articleOriginal);
    return Ok();
}

Mapping:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<ArticleViewModel, Article>()
        .ForMember(x => x.Created, opt => opt.Ignore())
        .ForMember(x => x.Updated, opt => opt.Ignore());

    cfg.CreateMap<DescriptionViewModel, Description>()
        .ForMember(x => x.Created, opt => opt.Ignore())
        .ForMember(x => x.Updated, opt => opt.Ignore())
        .ForMember(x => x.ArticleId, opt => opt.Ignore())
        .ForMember(x => x.Article, opt => opt.Ignore());
}
Mapper.AssertConfigurationIsValid();

Viewmodels:

public class ArticleViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public List<DescriptionViewModel> Descriptions { get; set; }
}

public class DescriptionViewModel
{
    public int Id { get; set; }

    public string Heading { get; set; }
}

Models:

public class Article : IEntity<int>
{
    public Article()
    {
        Descriptions = new List<Description>();
    }

    [Key]
    public int Id { get; set; }

    public DateTime Created { get; set; }

    public DateTime Updated { get; set; }

    [MaxLength(256)]
    public string Name { get; set; }

    public virtual ICollection<Description> Descriptions { get; set; }
}

public class Description: IEntity<int>
{
    [Key]
    public int Id { get; set; }

    public DateTime Created { get; set; }

    public DateTime Updated { get; set; }

    [MaxLength(256)]
    public string Heading { get; set; }

    public int ArticleId { get; set; }

    public virtual Article Article { get; set; }
}
Ogglas
  • 62,132
  • 37
  • 328
  • 418

2 Answers2

3

Finally solved it after two days frustration. Installed AutoMapper.Collection from https://github.com/AutoMapper/AutoMapper.Collection

PM> Install-Package AutoMapper.Collection
PM> Install-Package AutoMapper.Collection.EntityFramework

All I had to change was cfg.AddCollectionMappers(); and EqualityComparison. Example:

Mapper.Initialize(cfg =>
{
    cfg.AddCollectionMappers();

    cfg.SetGeneratePropertyMaps<GenerateEntityFrameworkPrimaryKeyPropertyMaps<DbContext>>();

    cfg.CreateMap<ArticleViewModel, Article>(MemberList.Source)
        .EqualityComparison((src, dst) => src.Id == dst.Id);

    cfg.CreateMap<DescriptionViewModel, Description>(MemberList.Source)
        .EqualityComparison((src, dst) => src.Id == dst.Id);
}
Mapper.AssertConfigurationIsValid();
Ogglas
  • 62,132
  • 37
  • 328
  • 418
  • I am also facing the same problem. I installed both the packages but using AddCollectionMappers() is throwing error. It doesn't recognize this. It says 'IConfiguration' does not contain a definition for 'AddCollectionMappers'. Can you help me with that? – Sachin Parashar Oct 26 '18 at 11:38
  • Oops.. Such a silly mistake. Installed it in some other project. – Sachin Parashar Oct 26 '18 at 11:57
  • 1
    For some reason when I try to add the "AddCollectionMappers" it doesn't recognize it. I'm using Collection v4.0.0 and Automapper v7.0.1. I did install it in the appropriate project. – oscarcardoso Feb 15 '19 at 23:58
0

Have you tried this without lazy loading? I had some issues with EF Lazy Loading and AutoMapper myself. First of all it is very inefficient.

See related Answer.

miszczak
  • 136
  • 10