Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid circular references with AutoMapper?

Tags:

c#

automapper

I have the following models (and corresponding DTOs):

public class Link
{
    public int Id {get; set;}
    public int FirstLinkId {get; set;}
    public int SecondLinkId {get; set;}
    public virtual Link FirstLink {get; set;}
    public virtual Link SecondLInk {get; set;}
}

public class OtherObject
{
    public int Id {get; set;}
    public int LinkId {get; set;}
    public string Name {get; set;}
    public virtual Link Link {get; set;}
}

In my scenario, I can have a Link object where FirstLink and/or SecondLink can be null, references to other objects, or references to the same object.

Now I want to load an OtherObject entity from the db using EF. I load the entity itself and also the Link object associated with it. This is done perfectly by EF.

In this particular case, both FirstLink and SecondLink are the same as Link, therefore, when automapping from model to dto it just keeps on mapping into oblivion.

My mapping is:

Mapper.CreateMap<OtherObject, OtherObjectDto>().Bidirectional()
      .ForMember(model => model.LinkId, option => option.Ignore());

where Bidirectional() is this extension:

public static IMappingExpression<TDestination, TSource> Bidirectional<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    return Mapper.CreateMap<TDestination, TSource>();
}

Is there way to tell Automapper not to map further down the tree in this case?

like image 903
Ivan-Mark Debono Avatar asked Feb 10 '23 19:02

Ivan-Mark Debono


1 Answers

The way I would handle this is to create separate DTO objects for the children:

public class Employee
{
    public int Id {get; set;}
    public string Name { get; set; }
    public Employee Supervisor {get; set; }
}
public class EmployeeDto {
    public int Id {get; set;}
    public string Name { get; set; }
    public SupervisorDto Supervisor { get; set; }

    public class SupervisorDto {
        public int Id {get; set;}
        public string Name { get; set; }
    }
}
Mapper.CreateMap<Employee, EmployeeDto>();
Mapper.CreateMap<Employee, EmployeeDto.SupervisorDto>();

Don't let your DTOs be recursive/self-referential. Be explicit in your structure on how deep you want it to go.

EF can't do recursive joins, you're only doing one level, so don't make your DTOs go nuts with infinitely deep relationships. Be explicit.

like image 63
Jimmy Bogard Avatar answered Feb 20 '23 15:02

Jimmy Bogard