2017-10-04 85 views
1

我有一种情况,当我更新子表中的一行时,实体框架核心(2.0)正在向父表执行附加工作。我已经把原因固定在AutoMapper生成的unflattened对象树中没有设置的值(我并不是说它是AutoMapper中的一个错误,它可能与我的代码有关)。automapper unflatten排除父对象的值

我在API开发方面使用ASP.NET Core 2.0,C#,EF Core 2.0和AutoMapper。该数据库已经存在,并且EF类从它脚手架。

为了保持简短,子表是Note,父表是NoteType。是EF类(除去多余的栏)如下:

//Entity classes 
public partial class Note 
    { 
     public int NoteBookId { get; set; } 
     public short NoteSeqNo { get; set; } 
     public short NoteTypeId { get; set; } 
     public string NoteText { get; set; } 

     public NoteBook NoteBook { get; set; } 
     public NoteType NoteType { get; set; } 
    } 

public partial class NoteType 
    { 
     public NoteType() { Note = new HashSet<Note>(); } 
     public short NoteTypeId { get; set; } 
     public string NoteTypeDesc { get; set; } 
     public ICollection<Note> Note { get; set; } 
    } 

//DTO class 
    public class NoteDto 
    { 
     public int NoteBookId { get; set; } 
     public short NoteSeqNo { get; set; } 
     public short NoteTypeId { get; set; } 
     public string NoteTypeNoteTypeDesc { get; set; } 
     public string NoteText { get; set; } 
    } 

public class NoteTypeDto 
    { 
     public short NoteTypeId { get; set; } 
     public string NoteTypeDesc { get; set; } 
    } 
  • (NoteBookId + NoteSeqNo)是注的主键。
  • NoteTypeId是NoteType的主键。

配置

这是AutoMapper配置:

// config in startup.cs 
config.CreateMap<Note,NoteDto>().ReverseMap(); 
config.CreateMap<NoteType,NoteTypeDto>().ReverseMap(); 

读取数据

数据检索的结果我得到预期的结果和父记类型描述被填充。

// EF get note in repository 
      return await _dbcontext.Note 
       .Where(n => n.NoteId == noteId && n.NoteSeqNo == noteSeqNo) 
       .Include(n => n.NoteType) 
       .FirstOrDefaultAsync(); 

// Get note function in API controller 
       Note note = await _repository.GetNoteAsync(id, seq); 
       NoteDto noteDto = Mapper.Map<NoteDto>(note); 

例JSON结果:

{ 
    "noteBookId": 29, 
    "noteSeqNo": 19, 
    "noteTypeId": 18, 
    "noteTypenoteTypeDesc": "ABCDE", 
    "noteText": "My notes here." 
} 

更新数据

当该过程在更新期间反转,所述API控制器DTO映射到实体

Mapper.Map<Note>(noteDto) 

然后,当它通过代表传递给EF ository代码,EF尝试添加一个NoteType行ID为0。不平对象树看起来像这样:

Note 
    NoteBookId = 29 
    NoteSeqNo = 19 
    NoteTypeId = 18 
    NoteTypeNoteTypeDesc = "ABCDE" 
    NoteText = "My notes updated." 
    NoteType.NoteTypeDesc = "ABCDE" 
    NoteType.NoteTypeId = 0 

父ID柱(NoteType.NoteTypeId)值是0并且没有被分配18的值,其是我的预期。

(在调试过程中,我手动将NoteType.NoteTypeId设置为18,以确保EF对此没有任何影响)。

为了解决这个问题,我暂时在资源库代码中的Note中取消NoteType。

我是否应该期望AutoMapper使用setter填充所有的父属性,还是错过了一些配置?或许我的方法存在明显的缺陷?

回答

0

当AutoMapper反转映射时,它必须从扁平对象中收集嵌套对象的所有信息。您的DTO仅包含地图NoteType -> NoteTypeDesc的值。不是因为NoteType -> NoteTypeId,所以AM真的不知道从哪里获得价值。

如果你想只依靠扁平化,改变,唯一的办法是扁平NoteTypeId添加到DTO除了不平之一:

public class NoteDto 
{ 
    public int NoteBookId { get; set; } 
    public short NoteSeqNo { get; set; } 
    public short NoteTypeId { get; set; } // Not flattened 
    public short NoteTypeNoteTypeId { get; set; } // Flattened 
    public string NoteTypeNoteTypeDesc { get; set; } 
    public string NoteText { get; set; } 
} 

另一种方法是把它添加到您的映射:

config.CreateMap<Note, NoteDto>() 
    .ForMember(dest => dest.NoteTypeId, 
     e => e.MapFrom(src => src.NoteType.NoteTypeId)) 
    .ReverseMap(); 
+0

是的,但他说Note.NoteType不为空,并有Id 0,对不对? :)这是因为反转映射和默认的展平/解闭。 –

+0

我想这取决于目的是什么。如果目的是让Note.NoteType为空,我的答案适用,否则是你的。 –

+0

谢谢!该便士已经下降:)。额外的配置是我需要添加,以便unflattened id被填充。 (我不知道为什么我认为automapper会连接点)。 – Craig

0

MapFrom-s(包括默认解开)are reversed now。您可以放弃ReverseMap并创建地图,忽略Note.NoteType或忽略违规路径Note.NoteType.NoteTypeDesc。

+0

感谢您的评论,但我不明白你的建议如何帮助我。我不想放弃反向贴图,也不想忽略NoteType。我真的很想知道为什么AutoMapper不能完全解开NoteType。 – Craig

+0

您是否阅读过我链接的文档? :) –