7

I'm a little bit confused. I can't find out the difference between PreserveReferences and MaxDepth.

Let's suppose we have the following DTOs and models.

public class PersonEntity
{
    public PersonEntity InnerPerson { get; set; }
}

public class PersonModel
{
    public PersonModel InnerPerson { get; set; }
}

As written in the documentation:

Previously, AutoMapper could handle circular references by keeping track of what was mapped, and on every mapping, check a local hashtable of source/destination objects to see if the item was already mapped. It turns out this tracking is very expensive, and you need to opt-in using PreserveReferences for circular maps to work. Alternatively, you can configure MaxDepth.

My mappings:

cfg.CreateMap<PersonModel, PersonEntity>().MaxDepth(1);
cfg.CreateMap<PersonEntity, PersonModel>();

Program:

var personModel = new PersonModel();
personModel.InnerPerson = personModel;
var entity = Mapper.Map<PersonEntity>(personModel);

That is what I expect to get:

enter image description here

That is what I actually get:

enter image description here

I can use both of them (PreserveReferences and MaxDepth) for resolving circular references, but I don't see the difference. When I should use different number of depth in the MaxDepth method? So, could someone provide it? Thanks in advance.

Joseph Katzman
  • 1,959
  • 6
  • 21
  • 47

2 Answers2

7

MaxDepth doesn't consider object values at runtime. It simply stops mapping after the depth of the mapping tree reaches the configured value.

PreserveReferences doesn't help with ProjectTo, MaxDepth does. If somehow, with Map, you have a mapping tree that might overflow the stack, but objects instances are not duplicated, then PreserveReferences won't help, MaxDepth will.

MaxDepth is predictable, it stops at a hardcoded value, PreserveReferences stops only when an object instance is duplicated.

Paritosh
  • 11,144
  • 5
  • 56
  • 74
Lucian Bargaoanu
  • 3,336
  • 3
  • 14
  • 19
  • Could you provide a simple examples? It still has hard to understand it for me. Why `PreserveReferences` doesn't prevent stack overflowing? I successfully used it for my circular references. – Joseph Katzman Feb 16 '18 at 10:45
  • It works because the object instances are duplicated, it won't work otherwise. MaxDepth will work regardless. – Lucian Bargaoanu Feb 16 '18 at 10:53
  • Seems like I got it. If I will have the different instance of the `PersonEntity` in the `InnerPerson` property each time it will cause stack overflow exception and `PreserveReferences` won't help me. Am I correct? – Joseph Katzman Feb 16 '18 at 10:58
1

Thanks @Lucian Bargaoanu for the answer. I just want to add a simple example of MaxDepth.

I recently changed my DTOs and models.

public class SelfEntity
{
    public string Id { get; set; }
    public string Name { get; set; }
    public int Number;
    public SelfEntity InnerSelfEntity { get; set; }
}

public class SelfModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Number;
    public SelfModel InnerSelfModel { get; set; }
}

Mappings:

cfg.CreateMap<SelfModel, SelfEntity>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(x => x.Id.ToString()))
.MaxDepth(3);

Program:

SelfModel firstSelfModel = new SelfModel();
SelfModel prev = firstSelfModel;

for (int i = 0; i < 100; i++)
{
   SelfModel newModel = new SelfModel
   {
      Id = Guid.NewGuid(),
      Name = "Test name" + i.ToString(),
      Number = i
   };

   prev.InnerFirstSelf = newModel;
   prev = newModel;
}

var entity = Mapper.Map<FirstSelfEntity>(firstSelfModel);

Starts from the 3-th level of depth we will get null for the InnerSelfModel.

PreserveReferences doesn't help with ProjectTo, MaxDepth does. If somehow, with Map, you have a mapping tree that might overflow the stack, but objects instances are not duplicated, then PreserveReferences won't help, MaxDepth will.

Joseph Katzman
  • 1,959
  • 6
  • 21
  • 47