Automapper Circular Reference 无限循环
Automapper Circular Reference Infinite loops
我在使用 AutoMapper 时遇到一些问题,我映射的对象会产生循环引用,因此我无法return它JSON 使用 ActionResult 查看。
我已经将一个 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;
}
}
功能模式:
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 型号:
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 配置:
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:
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; }
}
然后调用:
List<MasterJobsDTO> mjd = Mapper.Map<List<function>, List<MasterJobsDTO>>(data);
我在浏览器中得到的错误是:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.job_family_D3FE2013BDB6002B7BE94915E73AEA531401...
谢谢!
在您的自动映射器配置中,您可以排除有问题的循环引用点。
.ForMember(dest => dest.OffendingVariable, source=> source.Ignore());
自动映射器完成后得到的结果对象将比 "entity" 对象 "smaller" 并且可以毫无问题地序列化为 JSON。
编辑:如果您真正的错误在于您最终希望能够将您的 "infinite" 对象序列化为 JSON,并且您不关心通过摆弄 automapper i 来修复它可以建议 "cropping" 沿着你的对象的圆点背面,像这样:
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>();
如果 pointBackMember 是一个列表,那么 select 从它开始并将它投射到你需要的深度
jsonPrepMJD 将是可序列化的。
等等,是自动映射器的问题还是 json 格式化程序无法处理循环引用 (CR)?
如果是 json,您可以配置 api 来处理 CR。 Here is a link to an overly academic example of how to have it ignore the CR. Here 是设置的选项。我能够在 WebApiConfig.cs
中全局解决该问题
就我个人而言,我宁愿 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;
}
}
我 运行 遇到了新版本自动映射器的类似问题。 Automapper 应该能够 statically figure out the CRs in 6.1+ 但我有一个非常复杂的 dto 模型,其中包含许多 CR。我正在等待 automapper 团队解决我的问题。在此期间,我恢复到 4.2.1.0,一切正常。在我解决了 automapper 异常之后,我从 json 格式化程序中得到了一个异常,上面的忽略配置解决了我的问题。
Here 是让我在 json 问题上走上正轨的原因。
我在使用 AutoMapper 时遇到一些问题,我映射的对象会产生循环引用,因此我无法return它JSON 使用 ActionResult 查看。
我已经将一个 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;
}
}
功能模式:
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 型号:
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 配置:
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:
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; }
}
然后调用:
List<MasterJobsDTO> mjd = Mapper.Map<List<function>, List<MasterJobsDTO>>(data);
我在浏览器中得到的错误是:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.job_family_D3FE2013BDB6002B7BE94915E73AEA531401...
谢谢!
在您的自动映射器配置中,您可以排除有问题的循环引用点。
.ForMember(dest => dest.OffendingVariable, source=> source.Ignore());
自动映射器完成后得到的结果对象将比 "entity" 对象 "smaller" 并且可以毫无问题地序列化为 JSON。
编辑:如果您真正的错误在于您最终希望能够将您的 "infinite" 对象序列化为 JSON,并且您不关心通过摆弄 automapper i 来修复它可以建议 "cropping" 沿着你的对象的圆点背面,像这样:
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>();
如果 pointBackMember 是一个列表,那么 select 从它开始并将它投射到你需要的深度
jsonPrepMJD 将是可序列化的。
等等,是自动映射器的问题还是 json 格式化程序无法处理循环引用 (CR)?
如果是 json,您可以配置 api 来处理 CR。 Here is a link to an overly academic example of how to have it ignore the CR. Here 是设置的选项。我能够在 WebApiConfig.cs
中全局解决该问题就我个人而言,我宁愿 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;
}
}
我 运行 遇到了新版本自动映射器的类似问题。 Automapper 应该能够 statically figure out the CRs in 6.1+ 但我有一个非常复杂的 dto 模型,其中包含许多 CR。我正在等待 automapper 团队解决我的问题。在此期间,我恢复到 4.2.1.0,一切正常。在我解决了 automapper 异常之后,我从 json 格式化程序中得到了一个异常,上面的忽略配置解决了我的问题。
Here 是让我在 json 问题上走上正轨的原因。