Skip to main content
 首页 » 编程设计

c#之自引用循环导致 map 堆栈溢出

2024年02月27日39duanxz

根据文档 PreserveReferences 应尽可能为 AutoMapper 自动设置。

Starting from 6.1.0 PreserveReferences is set automatically at config time whenever possible.

https://github.com/AutoMapper/AutoMapper/wiki/5.0-Upgrade-Guide

我也尝试过将 MaxDepth 设置为 1,但我仍然遇到以下映射的堆栈溢出异常。我能以某种方式解决这个问题还是需要修改 View 模型?

cfg.CreateMap<ArticleViewModel, Article>(MemberList.Source) 
    .MaxDepth(1) 
    .EqualityComparison((src, dst) => src.Id == dst.Id); 

导致栈溢出异常的代码:

var article = await iArticleRepository.GetAsync(id); 
//The mapping below causes the exception 
var mappedArticle = Mapper.Map<ArticleViewModel>(article); 

实体:

public class Article: IEntity<int> 
{ 
    [Key] 
    public int Id { get; set; } 
 
    ... 
 
    public int SupplierId { get; set; } 
 
    public virtual Supplier Supplier { get; set; } 
} 
 
public class Supplier: IEntity<int> 
{ 
    [Key] 
    public int Id { get; set; } 
 
    ... 
 
    public virtual ICollection<Contact> Contacts { get; set; } 
} 
 
public class Contact: IEntity<int> 
{ 
    [Key] 
    public int Id { get; set; } 
 
    ... 
    public virtual ICollection<Supplier> Suppliers { get; set; } 
} 

查看模型:

public class ArticleViewModel 
{ 
    public int Id { get; set; } 
 
    ... 
    public SupplierViewModel Supplier { get; set; } 
 
} 
 
public class SupplierViewModel 
{ 
    public int Id { get; set; } 
 
    ... 
    public List<ContactViewModel> Contacts { get; set; } 
 
} 
 
public class ContactViewModel 
{ 
    public int Id { get; set; } 
    ...  
    public List<SupplierViewModel> Suppliers { get; set; } 
} 

请您参考如下方法:

嗯,不清楚只要有可能 是什么意思。由于之前的文档说明

It turns out this tracking is very expensive, and you need to opt-in using PreserveReferences for circular maps to work

看起来你的场景不符合不可能类别:)

不要依赖它并使用显式选择加入。此示例模型中的循环引用位于 Supplier 和 Contact 之间,因此您必须在涉及的类映射之一中指定,例如:

cfg.CreateMap<ArticleViewModel, Article>(MemberList.Source) 
    .MaxDepth(1) 
    .EqualityComparison((src, dst) => src.Id == dst.Id); 
 
cfg.CreateMap<SupplierViewModel, Supplier>(MemberList.Source) 
    .PreserveReferences() 
    .EqualityComparison((src, dst) => src.Id == dst.Id);