Search code examples
c#modelreferenceautomapperpoco

AutoMapper, how to keep references between mapped objects?


I am using AutoMapper to convert a UI model to POCOs that I later serialize to XML using a DataContractSerializer in order to preserve the references between them.

The problem comes that, when mapping, the references between those entities are lost.

The UI classes reference each other, but the mapping process makes new instances for every reference, so the original relations are broken :(

Let me explain:

I have 2 entities of type Person

    Person 
    { 
        List<House> OwnedHouses 
    }

And these 2 objects

John who owns

  • House1

Will who also owns

  • House1

When AutoMapper maps each Person correctly, but when it also maps House1 as two different instances!!

So I have a two copies of House1. John owns his House1 (#1) and Will owns his House1 (#2).

They are not linked anymore.

Is there any way to keep the relations that originally existed?

Thanks.

EDITED: Actually what I have is this:

A Document contains a list of ChildDocuments. Each ChildDocument has a list of Designables (Rectangles, Lines, Ellipses…) and a especial designable called ChildDocumentAdapter that contains itself ANOOTHER ChildDocument. This is the trouble, it can reference another ChildDocument.

The diagram


Solution

  • If I'm understanding the question, you're performing two separate mapping operations - one for John, another for Will.

    @Sunny is right. AutoMapper is not designed to do this. Each call you make to Mapper.Map() is typically independent of any other. By using the same instance of the HouseListConverter, you get the benefit of caching all mapped houses in a dictionary. But you have to either register it globally or pass it as an option to the mapping calls you want grouped together. That's not just extra work, it's hiding a very important implementation detail deep within the converter.

    If you map both John and Will in one operation, by putting them into a collection, the output would be what you want without the need for a custom converter or resolver.

    It may be an easier alternative for other people with a similar problem.

    public void MapListOfPeopleWithSameHouse()
    {
        Mapper.CreateMap<Person, PersonDTO>();
        Mapper.CreateMap<House, HouseDTO>();
    
        var people = new List<Person>();
        var house = new House() { Address = "123 Main" };
        people.Add(new Person() { Name = "John", Houses = new List<House>() { house } });
        people.Add(new Person() { Name = "Will", Houses = new List<House>() { house } });
    
        var peopleDTO = Mapper.Map<List<PersonDTO>>(people);
        Assert.IsNotNull(peopleDTO[0].Houses);
        Assert.AreSame(peopleDTO[0].Houses[0], peopleDTO[1].Houses[0]);
    }