我在使用Automapper Projections在我的应用程序中处理自引用模型时遇到了问题。这就是我的模型的样子:
public class Letter
{
public int? ParentId {get; set;}
public Letter ParentLetter {get; set;
public int Id {get; set;}
public string Title {get; set;}
public string Content {get; set;}
public DateTime? ReceivedTime {get; set;}
public DateTime? SendingTime {get; set;}
public List<Destination> Destinations {get; set;}
public List<Letter> Responses {get; set;}
}
public class LetterView
{
public int? ParentId {get; set;}
public int Id {get; set;}
public string Title {get; set;}
public string Content {get; set;}
public DateTime? ReceivedTime {get; set;}
public DateTime? SendingTime {get; set;}
public List<DestinationView> Destinations {get; set;}
public List<LetterView> Responses {get; set;}
}
public class Destination
{
public int Id {get; set;}
public string Name {get; set;}
..
}
public class DestinationView
{
public int Id {get; set;}
public string Name {get; set;}
}
// The mapping:
CreateMap<Destination, DestinationView>
CreateMap<Letter, LetterView>
我的问题是将Letter映射到LetterView。问题出现在响应的某个地方,我只是无法弄清楚应该改变什么。
每当运行单元测试和断言映射配置时,一切都可以正常工作,以及将具有多个响应的字母映射到视图模型。 但是,每当我从数据库(实体框架6)收到一封带有它的resposnes信件时,对LetterView的投射会抛出一个stackoverflow异常。
任何人都可以解释一下为什么这只会在投影时发生?我应该改变什么?
答案 0 :(得分:1)
这里有几个选项,但通常最好的选择是在响应上设置最大深度。 AutoMapper将尝试捕获属性,并且您已经拥有自引用DTO。首先试试这个:
CreateMap<Letter, LetterView>()
.ForMember(d => d.Responses, opt => opt.MaxDepth(3));
另一种选择是以特定深度预先连接DTO。您将创建一个LetterView和一个ChildLetterView。您的ChildLetterView没有&#34;响应&#34;属性,在您的DTO方面为您提供2个级别的深度。您可以根据需要进行深度调整,但在DTO类型中非常明确,它们位于具有Parent / Child / Grandchild / Greatgrandchild类型名称的层次结构中。
答案 1 :(得分:0)
您的DbContext上可能已启用lazy loading。循环引用可能会产生堆栈溢出异常。避免它的最好方法是禁用延迟加载:
context.ContextOptions.LazyLoadingEnabled = false;
// Bring entity from database then reenable lazy loading if needed
context.ContextOptions.LazyLoadingEnabled = true;
但是,您需要include所有必需的导航属性,因为在延迟加载延迟加载时EntityFramework不会将它们恢复。如果您需要其他请求,请不要忘记重新启用它。