简体   繁体   English

自动映射器循环参考无限循环

[英]Automapper Circular Reference Infinite loops

I have some problems with AutoMapper, the object that i mapped makes circular reference, and because of this I can't return it JSON to View using ActionResult. 我在使用AutoMapper时遇到了一些问题,我映射的对象做出了循环引用,因此,我无法使用ActionResult将其JSON返回给View。

I've made an DTO's object linked with another two. 我已经将DTO的对象与另外两个对象链接在一起。

 public class MasterJobsDTO
{
    public int function_id { get; set; }
    public string function_name { get; set; }
    public bool is_active { get; set; }
    public job_family job_family
    {
        get; set;

    }
    public functional_area functional_area
    {
        get; set;

    }
}

Function mode: 功能模式:

 public partial class function
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public function()
    {
        this.t_actual_organization = new HashSet<t_actual_organization>();
        this.t_actual_organization_split_position = new HashSet<t_actual_organization_split_position>();
    }

    public int function_id { get; set; }
    public string function_name { get; set; }
    public bool is_active { get; set; }
    public Nullable<int> job_family_id { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization> t_actual_organization { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization_split_position> t_actual_organization_split_position { get; set; }
    public virtual job_family job_family { get; set; }
}

Job_Family model: Job_Family模型:

public partial class job_family
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public job_family()
    {
        this.t_actual_organization = new HashSet<t_actual_organization>();
        this.t_actual_organization_split_position = new HashSet<t_actual_organization_split_position>();
        this.functions = new HashSet<function>();
    }

    public int job_family_id { get; set; }
    public string job_family_name { get; set; }
    public Nullable<int> functional_area_id { get; set; }

    public virtual functional_area functional_area { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization> t_actual_organization { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization_split_position> t_actual_organization_split_position { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<function> functions { get; set; }
}

Automapper config: 自动映射器配置:

cfg.CreateMap<function, MasterJobsDTO>().MaxDepth(1).PreserveReferences()
        .ForMember(x => x.functional_area_id, opts => opts.MapFrom(source => source.job_family.functional_area.functional_area_id))
        .ForMember(x => x.functional_area_extended_name, opts => opts.MapFrom(source => source.job_family.functional_area.functional_area_extended_name))
        .ForMember(x => x.job_family_name, opts => opts.MapFrom(source => source.job_family.job_family_name))
        .ForMember(x => x.functional_area, opts => opts.MapFrom(source => source.job_family.functional_area))
        ;

function_area class: function_area类:

 public partial class functional_area
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public functional_area()
    {
        this.job_family = new HashSet<job_family>();
        this.t_actual_organization = new HashSet<t_actual_organization>();
        this.t_actual_organization_split_position = new HashSet<t_actual_organization_split_position>();
    }

    public int functional_area_id { get; set; }
    public string functional_area_name { get; set; }
    public string functional_area_extended_name { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<job_family> job_family { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization> t_actual_organization { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<t_actual_organization_split_position> t_actual_organization_split_position { get; set; }
}

And the call: 并致电:

List<MasterJobsDTO> mjd = Mapper.Map<List<function>, List<MasterJobsDTO>>(data);

The error that i get in browser is: 我在浏览器中得到的错误是:

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.job_family_D3FE2013BDB6002B7BE94915E73AEA531401... 序列化类型为'System.Data.Entity.DynamicProxies.job_family_D3FE2013BDB6002B7BE94915E73AEA531401 ...的对象时检测到循环引用

Thank you! 谢谢!

In your automapper config you can exclude the offending circular reference pointback. 在您的自动映射器配置中,您可以排除有害的循环参考点。

.ForMember(dest => dest.OffendingVariable, source=> source.Ignore());

The resulting object you get after the automapper finishes will be "smaller" than the "entity" one and can be serialised to JSON without issue. 自动映射器完成后得到的结果对象将比“实体”“小”,并且可以序列化为JSON而不会出现问题。

EDIT: If your true error lies in that you ultimately want to be able to serialise your "infinite" object into JSON, an you don't care about fixing it by fiddling with automapper i can propose "cropping" down the circular point backs of your object with something like this: 编辑:如果您的真正错误在于您最终希望能够将“无限”对象序列化为JSON,那么您不关心通过摆弄automapper来修复它的问题,我可以建议将“无限”对象的圆点缩减像这样的对象:

List<MasterJobsDTO> mjd = Mapper.Map<List<function>, List<MasterJobsDTO>>(data);

var jsonPrepMJD = new List<MasterJobsDTO>(from m in mjd
                            select new MasterJobsDTO()
                            {
                              id = m.id,
                              ...,
                              pointBackMember = new PointBackMember(){set all but the virtual pointback}
                            }.Cast<MasterJobsDTO>();

If the pointBackMember is a list then select from it and cast it too as deep as you need to go 如果pointBackMember是一个列表,则从中选择并根据需要将其投射到尽可能深的位置

jsonPrepMJD would then be serialisable. 然后jsonPrepMJD将是可序列化的。

Wait, so is the problem with automapper or is it that the json formatter can't handle the circular reference (CR)? 等等,这是automapper的问题,还是json格式器无法处理循环引用(CR)?

If it is the json you can configure your api to handle the CR. 如果是json,则可以配置api以处理CR。 Here is a link to an overly academic example of how to have it ignore the CR. 是一个过于学术性的示例的链接,该示例说明了如何忽略CR。 Here are the options for the setting. 是该设置的选项。 I was able to resolve the issue globally in my WebApiConfig.cs 我可以在WebApiConfig.cs中全局解决此问题

Personally I'd rather be able to have the json be able to represent the data correctly than change my coding practices because I can only go X levels deep. 就我个人而言,我宁愿能够使json能够正确表示数据,而不是更改我的编码实践,因为我只能深入X级。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
        //this will ignore
        json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        //this will serialize them to objects.
        json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
        json.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
     }
}

I ran into a similar issue with new versions of automapper. 我在新版本的automapper中遇到了类似的问题。 Automapper is supposed to be able to statically figure out the CRs in 6.1+ but I had a very complex dto model with many CRs. Automapper应该能够静态计算6.1+中的CR,但是我有一个非常复杂的dto模型,其中包含许多CR。 I am waiting for the automapper team to resolve my issue. 我正在等待自动映射器团队解决我的问题。 In the interim I reverted to 4.2.1.0 and everything worked. 在此期间,我恢复到4.2.1.0,一切正常。 After I resolved the automapper exceptions I got a exception from the json formatter and the ignore configuration above solved my issue. 解决自动映射器异常后,我从json格式化程序收到了异常,并且上面的忽略配置解决了我的问题。

Here is what led me on the right track for the json issue. 就是引导我走上json问题正确道路的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM