У меня возникла ситуация, когда ядро 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 заполнит все родительские свойства сеттерами, или я пропустил какую-то настройку? Возможно, в моем подходе есть вопиющий изъян?