automapper unflatten从父对象中排除值 [英] automapper unflatten excludes value from parent object
问题描述
当我更新子表中的一行时,实体框架核心(2.0)正在对父表执行其他工作.我已经查明原因是未在AutoMapper生成的未展平的对象树中设置一个值(我并不是说这是AutoMapper中的错误;这可能与我的代码有更多关系).
I've a situation where entity framework core (2.0) is performing additional work to a parent table when I update a row in a child table. I've pin-pointed the cause to a value not being set in the unflattened object tree produced by AutoMapper (I'm not saying it is an error in AutoMapper; it's probably more to do with my code).
我正在使用ASP.NET Core 2.0,C#,EF Core 2.0和AutoMapper进行API开发.该数据库已经存在,并且EF类已经从该数据库中被搭建起来.
I'm using ASP.NET Core 2.0, C#, EF Core 2.0 and AutoMapper for the API development side. The database already exists and the EF classes scaffolded from it.
为简短起见,子表为Note,父表为NoteType. EF类(删除了外部列)如下:
To keep it short, the child table is Note and the parent table is NoteType. The EF classes (extraneous columns removed) are as follows :
//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)是Note的主键.
- NoteTypeId是NoteType的主键.
配置
这是AutoMapper配置:
This is the AutoMapper configuration:
// config in startup.cs
config.CreateMap<Note,NoteDto>().ReverseMap();
config.CreateMap<NoteType,NoteTypeDto>().ReverseMap();
读取数据
作为数据检索的结果,我得到了预期的结果,并且填充了父注释类型描述.
As a result of data retrieval I get the expected result and the parent note type description is populated.
// 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映射到实体
When the process is reversed during an update, the API controller maps the dto to the entity
Mapper.Map<Note>(noteDto)
然后,当存储库代码将其传递给EF时,EF尝试添加ID为0的NoteType行.未展平的对象树如下所示:
Then when it is passed to EF by the repository code, EF tries to add a NoteType row with id 0. The unflattened object tree looks like this:
Note
NoteBookId = 29
NoteSeqNo = 19
NoteTypeId = 18
NoteTypeNoteTypeDesc = "ABCDE"
NoteText = "My notes updated."
NoteType.NoteTypeDesc = "ABCDE"
NoteType.NoteTypeId = 0
父ID列(NoteType.NoteTypeId)的值为0,并且未分配18的值,这是我期望的值.
The parent id column (NoteType.NoteTypeId) value is 0 and is not assigned the value of 18 which is what I expected.
(在调试过程中,我将NoteType.NoteTypeId手动设置为18,以确保EF对其不执行任何操作.)
(During debugging I manually set NoteType.NoteTypeId to 18 to ensure EF did nothing with it).
要解决此问题,我现在将存储库代码中注释"中的NoteType无效.
To work around this at the moment I nullify the NoteType in the Note in the repository code.
我应该让AutoMapper用setter填充所有父属性,还是错过一些配置?也许我的方法存在明显的缺陷?
Should I expected AutoMapper to populate all the parent properties with setters or have I missed some configuration? Perhaps there is a glaring flaw in my approach?
推荐答案
当AutoMapper反转映射时,它必须从平面对象收集嵌套对象的所有信息.您的DTO仅携带映射NoteType -> NoteTypeDesc
的值.不是NoteType -> NoteTypeId
,因此AM确实不知道从何处获得该价值.
When AutoMapper reverses the mapping, it has to collect all information for nested objects from the flat object. Your DTO only carries a value for the mapping NoteType -> NoteTypeDesc
. Not for NoteType -> NoteTypeId
, so AM really doesn't have any idea where to get that value from.
如果您只想依靠拼合,唯一的更改方法是在DTO上添加除拼合之外的拼合NoteTypeId
:
If you want to rely on flattening only, the only way to change that is to add a flattened NoteTypeId
to the DTO besides the unflattened one:
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; }
}
另一种方法是将其添加到您的映射中:
The alternative is to add this to your mapping:
config.CreateMap<Note, NoteDto>()
.ForMember(dest => dest.NoteTypeId,
e => e.MapFrom(src => src.NoteType.NoteTypeId))
.ReverseMap();
这篇关于automapper unflatten从父对象中排除值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!