【问题标题】:How to ignore property of property in AutoMapper mapping?如何忽略 AutoMapper 映射中的属性?
【发布时间】:2017-12-31 01:46:09
【问题描述】:

为具有多对多关系的 PersonGroup 类创建图像。一个人有一个组列表,一个组有一个人员列表。

Person 映射到PersonDTO 时,我有一个stack overflow exception,因为AutoMapper 无法处理Person>Groups>Members>Members>Groups>Members>...

下面是示例代码:

public class Person
{
    public string Name { get; set; }
    public List<Group> Groups { get; set; }
}

public class Group
{
    public string Name { get; set; }
    public List<Person> Members { get; set; }
}

public class PersonDTO
{
    public string Name { get; set; }
    public List<GroupDTO> Groups { get; set; }
}

public class GroupDTO
{
    public string Name { get; set; }
    public List<PersonDTO> Members { get; set; }
}

当我使用 .ForMember 创建映射器时,第一个执行的映射器会抛出 null reference exception

这是映射器的代码:

CreateMap<Person, PersonDTO>()
    .ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore())
    .ReverseMap();

CreateMap<Group, GroupDTO>()
    .ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore())
    .ReverseMap();

那么我错过了什么或做错了什么?当我删除 .ForMember 方法时,null reference exception 不再被抛出。

更新:我真的想强调我的问题的要点如何忽略一个属性的属性。这段代码只是一个比较简单的例子。

更新 2:这就是我修复它的方法,非常感谢Lucian-Bargaoanu

CreateMap<Person, PersonDTO>()
    .ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore())
    .PreserveReferences() // This is the solution!
    .ReverseMap();

CreateMap<Group, GroupDTO>()
    .ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore())
    .PreserveReferences() // This is the solution!
    .ReverseMap();

感谢.PreserveReferences() 修复了循环引用!

【问题讨论】:

  • 谢谢@Esperadoce,但我的代码没有示例那么简单。我真的很想忽略 AutoMapper 中的 property of a property
  • 是的,你是对的,我删除了我的标志!
  • 你为什么不直接使用.ForMember(x =&gt; x.members, o =&gt; o.Ignore())
  • 你的问题是循环引用所以检查这个stackoverflow.com/a/11505745/2954082
  • @Esperadoce 谢谢,我会试试的。

标签: c# entity-framework automapper stack-overflow nullreferenceexception


【解决方案1】:

【讨论】:

  • 是的!哦,我的天哪,它修好了!太感谢了!我希望我不必使用很多丑陋的代码,但是哇,只需添加.PreserveReferences() 就可以修复它!再次感谢您。
  • 始终欢迎提供潜在解决方案的链接,但请add context around the link,以便您的其他用户知道它是什么以及为什么存在。 始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。 考虑到仅仅是指向外部站点的链接Why and how are some answers deleted? 的一个可能原因。
【解决方案2】:

我认为您遇到的问题来自错误的假设,即 PersonDTO.Groups 中的组与 GroupDTO 相同 - 如果没有无限依赖循环,情况就不可能如此。以下代码应该适合您:

CreateMap<Person, PersonDTO>()
    .ForMember(x => x.Groups, opt => opt.Ignore())
    .ReverseMap()
    .AfterMap((src, dest) => 
    {
        dest.Groups = src.Groups.Select(g => new GroupDTO { Name = g.Name }).ToList()
    });

CreateMap<Group, GroupDTO>()
    .ForMember(x => x.Members, opt => opt.Ignore())
    .ReverseMap()
    .AfterMap((src, dest) => 
    {
        dest.Members = src.Members.Select(p => new PersonDTO { Name = p.Name }).ToList()
    });

您基本上需要教 AutoMapper 在 PersonDTO.Groups 属性的情况下,它应该以不同的方式映射 GroupDTO 对象。

但我认为您的问题更像是架构问题而不是代码一。 PersonDTO.Groups 不应该是 GroupDTO 类型 - 你在这里只对特定用户所属的组感兴趣,而不是他组的其他成员。你应该有一些更简单的类型,比如:

public class PersonGroupDTO
{
    public string Name { get; set; }
}

(名称当然由您决定)仅识别组而不传递其他成员。

【讨论】:

  • 感谢您的回答。这就是我尝试过的方式,但它看起来并不那么干净,不得不制作一个单独的 DTO 来解决这个问题。我用一个非常简单的解决方案更新了我的问题,以使用 automapper 修复循环引用。
  • 只考虑到使用 PreserveReferences 会在一定程度上减慢自动映射器的速度:) 除了你没问题。
猜你喜欢
  • 1970-01-01
  • 2017-02-19
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多