Хобрук: Ваш путь к мастерству в программировании

automapper unflatten исключает значение из родительского объекта

У меня возникла ситуация, когда ядро ​​Entity Framework (2.0) выполняет дополнительную работу с родительской таблицей, когда я обновляю строку в дочерней таблице. Я указал причину того, что значение не было установлено в несвернутом дереве объектов, созданном AutoMapper (я не говорю, что это ошибка AutoMapper; вероятно, это больше связано с моим кодом).

Я использую ASP.NET Core 2.0, C#, EF Core 2.0 и AutoMapper для разработки API. База данных уже существует, и классы 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) — первичный ключ Note.
  • 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 пытается добавить строку NoteType с идентификатором 0. Несвернутое дерево объектов выглядит следующим образом:

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

Значение столбца родительского идентификатора (NoteType.NoteTypeId) равно 0, и ему не присваивается значение 18, как я и ожидал.

(Во время отладки я вручную установил для NoteType.NoteTypeId значение 18, чтобы гарантировать, что EF ничего с ним не сделает).

Чтобы обойти это, на данный момент я аннулирую NoteType в Note в коде репозитория.

Должен ли я ожидать, что AutoMapper заполнит все родительские свойства сеттерами, или я пропустил какую-то настройку? Возможно, в моем подходе есть вопиющий изъян?


Ответы:


1

Когда 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();
05.10.2017
  • Да, но он говорит, что Note.NoteType не равен нулю и имеет идентификатор 0, верно? :) Это из-за перевернутой карты и сглаживания/разглаживания по умолчанию. 05.10.2017
  • Думаю, это зависит от цели. Если цель состоит в том, чтобы иметь Note.NoteType null, применяется мой ответ, в противном случае ваш. 05.10.2017
  • Благодарю вас! Копейка упала :). Дополнительный конфиг — это то, что мне нужно было добавить, чтобы был заполнен несведенный идентификатор. (Я не знаю, почему я думал, что automapper соединит точки). 06.10.2017

  • 2

    MapFrom-s (включая развертку по умолчанию) теперь перевернуты . Вы можете удалить ReverseMap и создать карты, игнорировать Note.NoteType или игнорировать ошибочный путь, Note.NoteType.NoteTypeDesc.

    04.10.2017
  • Спасибо за ваш комментарий, но я не понимаю, как ваше предложение помогает мне. Я не хочу сбрасывать обратные карты и не хочу игнорировать NoteType. Мне бы очень хотелось знать, почему AutoMapper не полностью распаковывает NoteType. 05.10.2017
  • Новые материалы

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..