自动映射自引用模型投影

时间:2016-04-29 10:18:25

标签: c# entity-framework entity-framework-6 automapper

我在使用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异常。

任何人都可以解释一下为什么这只会在投影时发生?我应该改变什么?

2 个答案:

答案 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不会将它们恢复。如果您需要其他请求,请不要忘记重新启用它。