AutoMapper и Entity Framework Включить с круговыми отношениями без отслеживания - PullRequest
0 голосов
/ 14 мая 2018

Используя Entity Framework 6, я пытаюсь загружать свои Caller модели из базы данных, используя .AsNoTracking(), но у меня возникает затруднение, когда я пытаюсь сопоставить эти модели их ViewModels с помощью AutoMapper 6.

Caller имеет Address, что является отношением многие-к-одному (вызывающий может иметь один адрес, адрес может иметь несколько вызывающих).

Вот (уменьшенные) классы моделей (ViewModels почти идентичны)

public class Caller
{
    public Guid Id { get; set; }

    public string FirstName { get; set; }

    public Address Address { get; set; }
}

public class Address
{
    public Guid Id { get; set; }

    public string City { get; set; }

    public virtual  ICollection<Caller> Callers { get; set; }
}

Вот как я их отображаю

// Address
CreateMap<Address, AddressViewModel>()
    .ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
    .ForMember(vm => vm.CallerViewModels, map => map.MapFrom(m => m.Callers))
    .ForMember(vm => vm.City, map => map.MapFrom(m => m.City))
    .ReverseMap();

// Caller
CreateMap<Caller, CallerViewModel>()
    .ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
    .ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
    .ForMember(vm => vm.FirstName, map => map.MapFrom(m => m.FirstName))
    .ReverseMap();

В моем CallerRepository я использую эту функцию:

public async Task<Caller> GetFullCallerAsNoTrackingAsync(Guid id)
{
    return await _context.Callers
        .AsNoTracking()
        .Include(c => c.Address)
        .FirstOrDefaultAsync(c => c.Id == id);
}

Моя проблема происходит здесь:

// Map Caller to a CallerViewModel
Caller caller = await unitOfWork.CallerRepo.GetFullCallerAsNoTrackingAsync(Guid.Parse(callerId));
CallerViewModel callerViewModel = Mapper.Map<CallerViewModel>(caller); // Throws exception

Исключение, которое выдается, говорит

Типы отображения ошибок ... Caller.Address -> CallerViewModel.Address ... Когда объект возвращается с параметром слияния NoTracking, метод Load может быть вызван, только если EntityCollection или EntityReference не содержат объектов.

Это прекрасно работает, когда я удаляю .AsNoTracking(), но из соображений производительности я пытаюсь сохранить это.

Мне не нужно знать Caller -> Address -> Callers, мне просто нужно Caller -> Address

Любые предложения о том, как мне этого добиться?

<Ч />

Редактировать / Обновить:

Благодаря FoundNil ответ Мне удалось это сделать.

Я изменил свою карту Address на:


    CreateMap<Address, AddressViewModel>()
        .ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
        .ForMember(vm => vm.CallerViewModels, map => map<strike>.MapFrom(m => m.Callers)</strike>.Ignore())
        .ForMember(vm => vm.City, map => map.MapFrom(m => m.City))
        .ReverseMap();

И я сделал то же самое с другим свойством, CallDetailViewModels, на моей Caller -> CallerViewModel карте


    CreateMap<Caller, CallerViewModel>()
        .ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
        .ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
        .ForMember(vm => vm.CallDetailViewModels, map => map<strike>.MapFrom(m => m.CallDetails)</strike>.Ignore())

Сходство, которое я вижу между этим и Address, заключается в том, что Caller является родительским объектом Address, а CallDetail является родительским объектом Caller

Оба этих родителя были навигационными свойствами в соответствующем классе модели:

Caller -> public virtual ICollection<CallDetail> CallDetails { get; set; }
Address -> public virtual ICollection<Caller> Callers { get; set; }

Возможно, это может дать полезный флаг другим людям, где они могут столкнуться с этой проблемой.

Примечание: My CallDetail имеет отношение многие ко многим с Caller, поэтому оно также имеет свойство навигации Callers, и я не игнорирую это в моем CallDetail Карта.

1 Ответ

0 голосов
/ 14 мая 2018

Я не совсем уверен, почему это происходит, но я предполагаю, что проблема в том, что когда вы используете .AsNoTracking(), что-то происходит между Address -> Callers в контексте, поэтому больше нет способа отобразить ICollection<Caller> и его вид модели.

И так как вы упомянули, что хотите только Caller -> Address, вы должны попробовать эту карту:

// Address
CreateMap<Address, AddressViewModel>()
    .ForMember(x => x.Callers, opt => opt.Ignore())
    .ReverseMap();

// Caller
CreateMap<Caller, CallerViewModel>()
    .ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
    .ReverseMap();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...