AutoMapper throwing StackOverflowException when calling ProjectTo<T>() on IQueryable

六眼飞鱼酱① 提交于 2019-11-28 09:03:42
Jimmy Bogard

You have self-referencing entities AND self-referencing DTOs. Generally speaking self-referencing DTOs are a bad idea. Especially when doing a projection - EF does not know how to join together and join together and join together a hierarchy of items.

You have two choices.

First, you can force a specific depth of hierarchy by explicitly modeling your DTOs with a hierarchy in mind:

public class FieldDTO
{ 
    public int Id { get; set; }
    public string Name { get; set; }
    public List<TeacherDTO> Teachers { get; set; }
    public FieldDTO()
    {
        Teachers = new List<TeacherDTO>();
    }
}

public class TeacherDTO 
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string UserName => Email;
}

public class AppUserDTO : TeacherDTO
{
    public List<FieldDTO> Fields { get; set; }
    public AppUserDTO()
    {
         Fields = new List<FieldDTO>();
    }
}

This is the preferred way, as it's the most obvious and explicit.

The less obvious, less explicit way is to configure AutoMapper to have a maximum depth it will go to traverse hierarchical relationships:

CreateMap<AppUser, AppUserDTO>().MaxDepth(3);

I prefer to go #1 because it's the most easily understood, but #2 works as well.

Other option is using PreserveReferences() method.

CreateMap<AppUser, AppUserDTO>().PreserveReferences();

I use this generic method:

        public static TTarget Convert<TSource, TTarget>(TSource sourceItem)
    {
        if (null == sourceItem)
        {
            return default(TTarget);
        }

        var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace, ReferenceLoopHandling = ReferenceLoopHandling.Ignore };

        var serializedObject = JsonConvert.SerializeObject(sourceItem, deserializeSettings);

        return JsonConvert.DeserializeObject<TTarget>(serializedObject);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!