Alberto L. Bonfiglio
Alberto L. Bonfiglio

Reputation: 1835

Automapper with reciprocal navigation properties

need a bit of help here. I have a couple of classes that I am trying to map using Automapper. I am using EF core. The basic domain is like this:

Public class A 
{
  public string Id {get; set;}
  public string Name {get; set;}
  public virtual Icollection<AB> AB {get; set;} 
}

Public class B 
{
  public string Id {get; set;}
  public string Name {get; set;}
  public virtual ICollection<AB> AB {get; set;} 
}

Public class AB 
{
  public string A_Id {get; set;}
  public string B_Id {get; set;}
  public virtual A A {get; set;} 
}

My DTOs are like this:

Public class A_DTO 
{
  public string Id {get; set;}
  public string Name {get; set;}
  public ICollection<B> Bs {get; set;} 
}

Public class B_DTO 
{
  public string Id {get; set;}
  public string Name {get; set;}
  public ICollection<A> As {get; set;} 
}

Now where I get stuck is:

  1. How to set up the mapping so that Automapper automatically retrieves the list of children (e.g the relevant 'Bs' for the current 'A')
  2. How to configure my DTOs so that, for example, the retrieved 'Bs' for an 'A' do not expose the 'A's navigation property to prevent infinite recursion.

Thank you!

Upvotes: 2

Views: 953

Answers (2)

Himanshu Jain
Himanshu Jain

Reputation: 35

I know it's an old question but hopefully this helps someone.

You could call Automapper's ResolveUsing method like so :

cfg.CreateMap<A, A_DTO>()
 .ForMember(x => x.Bs,
 opt => opt.ResolveUsing(src => RemoveInclusions(src)));

And in RemoveInclusions method you can manually set B's navigation of A's to null like :

private B RemoveInclusions(A src)
{
  src.Bs.A = null;
  return src.Bs;
}

Upvotes: 1

Alberto L. Bonfiglio
Alberto L. Bonfiglio

Reputation: 1835

Partial answer here. I was researching and stumbled upon https://www.exceptionnotfound.net/entity-framework-and-wcf-loading-related-entities-with-automapper-and-reflection/

So I changed my DTOs by removing the navigation properties when the DTO is not the principal.

Public class A_DTO 
{
  public string Id {get; set;}
  public string Name {get; set;}
}

Public class A_Nav_DTO: A_DTO 
{
  public ICollection<B> Bs {get; set;} 
}

and in my mappings I did

CreateMap<A, A_DTO>();
CreateMap<A, A_Nav_DTO>()
  .ForMember(dto => dto.B, map => 
      map.MapFrom(model => 
          model.AB.Select(ab => ab.B).ToList()));

Now this works, but obviously now I have to map three classes instead of two. Any suggestions on how to improve this solution?

Upvotes: 1

Related Questions