automapper unflatten 从父对象中排除值
automapper unflatten excludes value from parent object
当我更新子项 table 中的行时,我遇到了 entity framework 核心 (2.0) 正在对父项 table 执行额外工作的情况。我已将原因确定为未在 AutoMapper 生成的未展平对象树中设置值(我并不是说这是 AutoMapper 中的错误;这可能与我的代码有关)。
我在 API 开发方面使用 ASP.NET Core 2.0、C#、EF Core 2.0 和 AutoMapper。数据库已经存在并且 EF 类 从它搭建了脚手架。
为了简短起见,子 table 是 Note,父 table 是 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 时,EF 尝试添加一个 id 为 0 的 NoteType 行。未展开的对象树如下所示:
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 填充所有父属性还是我错过了一些配置?也许我的方法有明显的缺陷?
MapFrom-s(包括默认的展开)are reversed now。您可以删除 ReverseMap 并创建地图,忽略 Note.NoteType 或忽略有问题的路径 Note.NoteType.NoteTypeDesc.
当AutoMapper 反转映射时,它必须从平面对象中收集嵌套对象的所有信息。您的 DTO 仅包含映射 NoteType -> NoteTypeDesc
的值。不适用于 NoteType -> NoteTypeId
,所以 AM 真的不知道从哪里获取该值。
如果你只想依赖扁平化,改变它的唯一方法是在 DTO 中添加一个扁平化的 NoteTypeId
除了未扁平化的之外:
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();
当我更新子项 table 中的行时,我遇到了 entity framework 核心 (2.0) 正在对父项 table 执行额外工作的情况。我已将原因确定为未在 AutoMapper 生成的未展平对象树中设置值(我并不是说这是 AutoMapper 中的错误;这可能与我的代码有关)。
我在 API 开发方面使用 ASP.NET Core 2.0、C#、EF Core 2.0 和 AutoMapper。数据库已经存在并且 EF 类 从它搭建了脚手架。
为了简短起见,子 table 是 Note,父 table 是 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 时,EF 尝试添加一个 id 为 0 的 NoteType 行。未展开的对象树如下所示:
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 填充所有父属性还是我错过了一些配置?也许我的方法有明显的缺陷?
MapFrom-s(包括默认的展开)are reversed now。您可以删除 ReverseMap 并创建地图,忽略 Note.NoteType 或忽略有问题的路径 Note.NoteType.NoteTypeDesc.
当AutoMapper 反转映射时,它必须从平面对象中收集嵌套对象的所有信息。您的 DTO 仅包含映射 NoteType -> NoteTypeDesc
的值。不适用于 NoteType -> NoteTypeId
,所以 AM 真的不知道从哪里获取该值。
如果你只想依赖扁平化,改变它的唯一方法是在 DTO 中添加一个扁平化的 NoteTypeId
除了未扁平化的之外:
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();