automapper unflatten从父对象中排除值 [英] automapper unflatten excludes value from parent object

查看:128
本文介绍了automapper unflatten从父对象中排除值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我更新子表中的一行时,实体框架核心(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆