Pet*_*ter 19 c# stack-overflow entity-framework automapper ef-code-first
我使用EF Code First创建了具有彼此集合的类.实体:
public class Field
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<AppUser> Teachers { get; set; }
public Field()
{
Teachers = new List<AppUser>();
}
}
public class AppUser
{
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string UserName => Email;
public virtual List<Field> Fields { get; set; }
public AppUser()
{
Fields = new List<FieldDTO>();
}
}
Run Code Online (Sandbox Code Playgroud)
DTO的:
public class FieldDTO
{
public int Id { get; set; }
public string Name { get; set; }
public List<AppUserDTO> Teachers { get; set; }
public FieldDTO()
{
Teachers = new List<AppUserDTO>();
}
}
public class AppUserDTO
{
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string UserName => Email;
public List<FieldDTO> Fields { get; set; }
public AppUserDTO()
{
Fields = new List<FieldDTO>();
}
}
Run Code Online (Sandbox Code Playgroud)
映射:
Mapper.CreateMap<Field, FieldDTO>();
Mapper.CreateMap<FieldDTO, Field>();
Mapper.CreateMap<AppUserDTO, AppUser>();
Mapper.CreateMap<AppUser, AppUserDTO>();
Run Code Online (Sandbox Code Playgroud)
我在调用此代码时遇到StackOverflowException(Context是我的dbContext):
protected override IQueryable<FieldDTO> GetQueryable()
{
IQueryable<Field> query = Context.Fields;
return query.ProjectTo<FieldDTO>();//exception thrown here
}
Run Code Online (Sandbox Code Playgroud)
我想这是因为它在列表中循环,无休止地互相呼叫.但我不明白为什么会这样.我的映射是错的吗?
Jim*_*ard 30
您有自引用实体和自引用DTO.一般来说,自引用DTO是一个坏主意.特别是在进行投影时 - EF不知道如何连接在一起并连接在一起并将项目层次结合在一起.
你有两个选择.
首先,您可以通过明确建立具有层次结构的DTO来强制特定深度的层次结构:
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>();
}
}
Run Code Online (Sandbox Code Playgroud)
这是首选方式,因为它是最明显和最明确的方式.
不那么明显,不太明确的方法是将AutoMapper配置为具有遍历层次关系的最大深度:
CreateMap<AppUser, AppUserDTO>().MaxDepth(3);
Run Code Online (Sandbox Code Playgroud)
我更喜欢去#1,因为它是最容易理解的,但#2也适用.
小智 9
其他选项是使用PreserveReferences()方法.
CreateMap<AppUser, AppUserDTO>().PreserveReferences();
Run Code Online (Sandbox Code Playgroud)