0

I've checked here on SO & Google in general for similar questions, but was not able to find an answer. This block of code should show my current scenario:

class Entity
{
  Guid EntityId { get; set; }
  string EntityName { get; set; }
  NestedEntity Nested { get; set; }
  // more domain methods
}

class NestedEntity
{
  Guid NestedId { get; set; }
  string NestedName { get; set; }
  string NestedDescription { get; set; }
  // more domain methods
}

class EntityDto
{
  Guid EntityId { get; set; }
  string EntityName { get; set; }
  NestedEntityDto Nested { get; set; }
}

class NestedEntityDto
{
  Guid NestedId { get; set; }
  string NestedName { get; set; }
  string NestedDescription { get; set; }
}

class MyMappingProfile : Profile
{
  CreateMap<Entity, EntityDto>();
  CreateMap<NestedEntity, NestedEntityDto>();
}

// that profile gets added to configuration, not shown here
// IMapper is registered and injected as a dependency, not shown here

EntityDto entityDto = GrabFromEntityFrameworkDbContext();

Entity entity = GrabChangesByUser();

mapper.Map<Entity, EntityDto>(entity, entityDto);

So, this is about updating an existing item, already persisted on DB, with changes made by user. An EntityDto instance is taken from Entity Framework, where DbContext will start tracking both EntityDto and NestedEntityDto. An Entity instance instead contains changes made by user, e.g. through a MVC/API PUT action.

mapper.Map<Entity, EntityDto>(entity, entityDto); represents a quick (for developer) way to deeply clone Entity into an existing instance of EntityDto.

Problem is that the instance of first-level entity is actually re-used (entityDto), but the same does not happen for nested entity instance. From my current tests, a new instance of NestedEntityDto is created and assigned to EntityDto. That screws up EF Change Tracking, because now there are two nested entity instances around with the same ID, etc.

So: how do I make AutoMapper reuse the same instance not only for first level destination object, but also for its nested properties? Is there a way to achieve this? Thanks all

Environment: ASP.NET Core 1.0, EF Core 1.0, AutoMapper 5.0.2, C#6

superjos
  • 12,189
  • 6
  • 89
  • 134
  • You may have to write a custom value resolver – Callum Linington Jul 22 '16 at 15:07
  • Fortunately for you Jimmy has just written an article on [Automapper and ASP.NET Core 1](https://lostechies.com/jimmybogard/2016/07/20/integrating-automapper-with-asp-net-core-di/) – Callum Linington Jul 22 '16 at 15:07
  • thanks for your feedback. Yes I'm aware of that post and integration in Net Core is not an issue, that's working. Could you elaborate more on your value resolver idea? We're already using one to convert some field into another. But I cannot see how it can allow you to re-use an existing instance below the top-level. – superjos Jul 22 '16 at 16:01
  • Well, after thinking about it. You're suppose to use to tools to make your work quicker and easier, if you're finding it too difficult, then just get automapper to map the value type properties and leave the the complex objects for manual mapping! I do that all the time, no problems – Callum Linington Jul 25 '16 at 07:50

1 Answers1

0

My solution, for time being, is basically drop using AutoMapper for mapping top-level classes (Entity & EntityDto), while keep using it to map nested classes.

In my scenario, top-level classes have a few properties, while there are more nested classes with their own properties, so my be-lazy balance brought me to have a custom mapper for manually mapping top-level classes and manually preserve instance. That takes an IMapper dependency in order to map nested classes and to also reuse existing instances when needed.

Of course this approach works because I'm interested in preserving instances only in top-level and 1st nested level. Again, it would not work if I had to preserve instances on levels further below.

EDIT: months later...
I incurred again in the same issue, this time being able to at least find some possible workarounds here on SO. For future readers:

Community
  • 1
  • 1
superjos
  • 12,189
  • 6
  • 89
  • 134