3

I have the following situation:

public class Parent : EntityObject
{
    EntityCollection<Child> Children { get; set; }
}

public class Child : EntityObject
{
    int Id { get; set; }
    string Value1 { get; set; }
    string Value2 { get; set; }
}

public class ParentViewModel
{
    List<ChildViewModel> Children { get; set; }
}

public class ChildViewModel
{
    int Id { get; set; }
    string Value1 { get; set; }
    string Value2 { get; set; }
}

Mapper.CreateMap<ParentViewModel, Parent>();

Mapper.CreateMap<ChildViewModel, Child>();

Is it possible to get AutoMapper to:

  • Map objects in the ParentViewModel.Children list to objects in the Parent.Children EntityCollection with matching Ids.
  • Create new objects in Parent.Children for objects in ParentViewModel.Children where an object with the id from source is not found in the destination list.
  • Remove objects from Parent.Children where the destination id does not exist in the source list.

Am I going about this all wrong?

lukeck
  • 4,528
  • 3
  • 27
  • 29

1 Answers1

4

I'm afraid automapper is not meant to be used for mapping to a populated object, it will erase the Parent.Children wen you invoke Map(). You have several approaches here:

  • Create the condition to execute the map on children youself:

     foreach (var childviewmodel in parentviewmodel.Children)
     {
         if (!parent.Children.Select(c => c.Id).Contains(childviewmodel.Id))
         {
             parent.Children.Add(Mapper.Map<Child>(childviewmodel));
         }
     }
    

Add more if()s for other behaviour

  • Create an IMappingAction and hook it in the BeforeMap method:

     class PreventOverridingOnSameIds : IMappingAction<ParentViewModel, Parent>
     {
         public void Process (ParentViewModel source, Parent destination)
         {
             var matching_ids = source.Children.Select(c => c.Id).Intersect(destination.Children.Select(d => d.Id));
             foreach (var id in matching_ids)
             {
                 source.Children = source.Children.Where(c => c.Id != id).ToList();
             }
         }
     }
    

..and later on

    Mapper.CreateMap<ParentViewModel, Parent>()
        .BeforeMap<PreventOverridingOnSameIds>();

this way you let automapper do the job.

WDRust
  • 3,663
  • 1
  • 19
  • 23
  • 2
    Thanks for this work around, very useful! However what did you mean by rethinking architecture, what would you suggest as an alternative? I was under the impression use of DTOs was good practise especially for managing things such as REST APIs. – David Chiew Oct 22 '15 at 05:41
  • 1
    It absolutely is, I don't remember what I meant with that. Edited it out since it doesn't really make much sense. – WDRust Mar 31 '16 at 05:20