automapper unflatten排除父对象的值
我有一种情况,当我更新子表中的一行时,实体框架核心(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填充所有的父属性,还是错过了一些配置?或许我的方法存在明显的缺陷?
当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();
MapFrom-s(包括默认解开)are reversed now。您可以放弃ReverseMap并创建地图,忽略Note.NoteType或忽略违规路径Note.NoteType.NoteTypeDesc。
感谢您的评论,但我不明白你的建议如何帮助我。我不想放弃反向贴图,也不想忽略NoteType。我真的很想知道为什么AutoMapper不能完全解开NoteType。 – Craig
您是否阅读过我链接的文档? :) –
是的,但他说Note.NoteType不为空,并有Id 0,对不对? :)这是因为反转映射和默认的展平/解闭。 –
我想这取决于目的是什么。如果目的是让Note.NoteType为空,我的答案适用,否则是你的。 –
谢谢!该便士已经下降:)。额外的配置是我需要添加,以便unflattened id被填充。 (我不知道为什么我认为automapper会连接点)。 – Craig