2016-08-11 195 views
1

我有两个实体(表)Person和Address。地址是Person的子实体。为什么AutoMapper不能映射我的子对象?

public class Person 
{ 
    public Person() 
    { 
     Addresses = new ObservableCollection<Address>(); 
    } 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DisplayName("Primary Key")] 
    [ScaffoldColumn(false)] 
    public int Id { get; set; } 

    [Required] 
    [DisplayName("First Name")] 
    [StringLength(25, MinimumLength = 3)] 
    public string FirstName { get; set; } 

    [DisplayName("Middle Name")] 
    [MaxLength(25)] 
    public string MiddleName { get; set; } 

    [Required] 
    [DisplayName("Last Name")] 
    [StringLength(25, MinimumLength = 3)] 
    public string LastName { get; set; } 

    public string FullName => $"{FirstName} {LastName}"; 

    [Required] 
    [DisplayName("Date of Birth")] 
    [DataType(DataType.Date)] 
    public DateTime BirthDate { get; set; } 

    public ObservableCollection<Address> Addresses { get; set; } 
} 


public class Address 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DisplayName("Primary Key")] 
    [ScaffoldColumn(false)] 
    public int Id { get; set; } 
    public int OwnerId { get; set; } 
    public Person Owner { get; set; } 
    public string Line1 { get; set; } 
    public string Line2 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 
} 

这两个表都有一个(几乎)镜像存档表,分别名为PersonArchive和AddressArchive。

public class PersonArchive 
{ 
    public PersonArchive() 
    { 
     Addresses = new ObservableCollection<AddressArchive>(); 
    } 

    [Key] 
    [DisplayName("Primary Key")] 
    [ScaffoldColumn(false)] 
    public int Id { get; set; } 

    [Required] 
    [DisplayName("First Name")] 
    [StringLength(25, MinimumLength = 3)] 
    public string FirstName { get; set; } 

    [DisplayName("Middle Name")] 
    [MaxLength(25)] 
    public string MiddleName { get; set; } 

    [Required] 
    [DisplayName("Last Name")] 
    [StringLength(25, MinimumLength = 3)] 
    public string LastName { get; set; } 

    public string FullName => $"{FirstName} {LastName}"; 

    [Required] 
    [DisplayName("Date of Birth")] 
    [DataType(DataType.Date)] 
    public DateTime BirthDate { get; set; } 

    public ObservableCollection<AddressArchive> Addresses { get; set; } 
} 

public class AddressArchive 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [DisplayName("Primary Key")] 
    [ScaffoldColumn(false)] 
    public int Id { get; set; } 
    public int OwnerId { get; set; } 
    public PersonArchive Owner { get; set; } 
    public string Line1 { get; set; } 
    public string Line2 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string ZipCode { get; set; } 
} 

在Person表的每个字段的类型相匹配,除了一个以外的地址字段是地址的集合的并在PeopleArchive相应字段的类型是AddressArchive的。地址的字段所有者也一样。

 using (ArchiveDemoContext context = new ArchiveDemoContext()) 
     { 

      //Person p = context.People.Include("Addresses").FirstOrDefault(); 
      Person p = context.People.FirstOrDefault(); 

      MapperConfiguration config = new MapperConfiguration(cfg => 
      { 
       cfg.CreateMap<Person, PersonArchive>() 
        .ForMember(dest => dest.Addresses, opt => opt.MapFrom(src => src.Addresses)); 
       cfg.CreateMap<Address, AddressArchive>() 
        .ForMember(dest => dest.Owner, opt => opt.MapFrom(src => src.Owner)); 
      }); 

      config.AssertConfigurationIsValid(); 

      IMapper mapper = config.CreateMapper(); 

      PersonArchive person = mapper.Map<Person, PersonArchive>(p); 
      //context.People.Remove(p); 

      context.PeopleArchive.Add(person); 

      context.SaveChanges(); 
     } 

调试代码不会给我任何例外,但是,只有人存档,而不是地址。

由于事先

+0

你确定你在''p'变量中获得'Address'数据吗?我会假设你是否真的遇到了一个循环引用异常,因为我猜测Address的'Owner'属性是引用回到同一个'Person'实例。 – MisterIsaak

+0

@MisterIsaak如果我使用.Include地址在那里。但是,这会使AutoMapper崩溃。 – Randy

+1

当它崩溃时,它是一个'System.StackOverflowException'吗? – MisterIsaak

回答

1

你不需要为你设置它的所有者ID地址,只要映射还给失主。改变你的映射:

cfg.CreateMap<Address, AddressArchive>() 
     .ForMember(dest => dest.Owner, opt => opt.Ignore()); 
+0

这就是我错过的。很好,谢谢。 – Randy

+1

我相信根据AutoMapper版本,模型也有[IgnoreMap]属性。 –