0

I am having an issue when mapping nested classes that reference each other. Entity framework populares the nested entities in a loop so I end up with the parent nested inside the nested child entity after mapping.

I made a sample program you can copy paste that shows the problem. In my actual program I am mapping collections so it would require to loop over entire collection to set all the nested object to null and that does not feel neat, I would rather adjust my mapping rules if possible.

Here is code that shows the issue:

using AutoMapper;

public class Job
{
    public string Name { get; set; }
    public PayPackage PayPackage { get; set; }
}

public class PayPackage
{
    public string Name { get; set; }
    public Job Job { get; set; }
}

public class JobViewModel
{
    public string Name { get; set; }
    public PayPackageViewModel PayPackage { get; set; }
}

public class PayPackageViewModel
{
    public string Name { get; set; }
    public JobViewModel Job { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        var job = new Job
        {
            Name = "Job Name",
            PayPackage = new PayPackage
            {
                Name = "Pay Package Name"
            }
        };

        job.PayPackage.Job = job; //simulate how EF is populating entity

        var config = new MapperConfiguration(c =>
        {
            c.CreateMap<Job, JobViewModel>();
            c.CreateMap<JobViewModel, Job>();
            c.CreateMap<PayPackage, PayPackageViewModel>();
            c.CreateMap<PayPackageViewModel, PayPackage>();
        });

        var mapper = config.CreateMapper();

        var jobVm = mapper.Map<JobViewModel>(job);

        Assert.IsTrue(jobVm.PayPackage != null);
        Assert.IsTrue(jobVm.PayPackage.Job == null); //how do I specify mapping so this passes?

    }
}

What is the best way to avoid the parent appearing twice in the mapped result?

Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • Out of curiosity - why do you want to do this? eg. Do you want to prevent a recursion exception when serializing? –  Mar 02 '18 at 03:47
  • So I don't return job twice for every record – Guerrilla Mar 02 '18 at 03:50
  • Both instances are references to the same object though. What real world issue is this causing your app? –  Mar 02 '18 at 04:29
  • In my app I have endpoint the returns collection of pay packages and the nested job details has the pay package nested again. So im returning the same data twice. It can be ignored but I'd rather not return same data twice – Guerrilla Mar 02 '18 at 04:36
  • Try MaxDepth. See https://stackoverflow.com/questions/48824263/automapper-what-is-the-difference-between-preservereferences-and-maxdepth/48824922#48824922. – Lucian Bargaoanu Mar 02 '18 at 05:17
  • I tried setting max depth to 1 for all maps and same thing still happens. – Guerrilla Mar 02 '18 at 20:48

1 Answers1

0

E.g.

c.CreateMap<Job, JobViewModel>()
 .ForMember(dest => dest.PayPackage, opt => opt.Ignore());

The PayPackage property of the destination JobViewModel object will be ignored when the mapping occurs.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • I want the paypackage inside job. I just dont want `Job.PayPackage.Job` recursively because then I am returning the job twice – Guerrilla Mar 02 '18 at 03:49
  • What I provided is just an example. If you want to ignore the `Job` property when mapping to `PayPackageViewModel` then make the appropriate adjustment. Are you saying, without actually saying, that a `PayPackageViewModel` will sometimes be a child of a `JobViewModel` and sometimes not and you want the mapping to be able to tell the difference? If so then I think you're out of luck, because you can't create a condition that uses anything other than the source and destination objects. – jmcilhinney Mar 02 '18 at 04:08
  • One potential option might be to add a call to `AfterMap` and check whether there is a child that has a child that is the same object as the current destination and, if so, set that grandchild property to `null`. It's probably not going to hep though, as you'd likely already suffered an infinite loop in the mapping. – jmcilhinney Mar 02 '18 at 04:10