AutoMapper не отображает объект внутри объекта

#c# #.net #automapper #asp.net-core-mvc

#c# #.net #automapper #asp.net-core-mvc

Вопрос:

AutoMapper в настоящее время не удаляет IpAddress объект внутри моего Server объекта. Конечная цель состоит в том, чтобы мой ввод уже был заполнен текущим IP-адресом в моем представлении редактирования. Однако, когда я помещаю точку останова в свой контроллер, IpAddress свойство имеет значение null, поэтому я не могу получить из него фактический адрес. Я знаю, что делаю что-то неправильно с AutoMapper, но пока не смог найти конкретное руководство. Заранее спасибо!

Экран точки останова

ServersController.cs

 public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var server = Mapper.Map<ServerViewModel>(await _context.Servers.SingleOrDefaultAsync(m => m.Id == id));
    if (server == null)
    {
        return NotFound();
    }
    return View(server);
}
  

ServerViewModel.cs

 public class ServerViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public OperatingSystem OS { get; set; }
    public MachineType MachineType { get; set; }
    public string AdminUserName { get; set; }
    public string AdminPassword { get; set; }
    public string EsxHost { get; set; }
    public int IpAddressId { get; set; }
    public IpAddress IpAddress { get; set; }

    public List<SelectListItem> GetOperatingSystems()
    {
        List<SelectListItem> operatingSystems = new List<SelectListItem>();
        Array values = Enum.GetValues(typeof(OperatingSystem));
        operatingSystems.Add(new SelectListItem
        {
            Text = "Select",
            Value = ""
        });

        foreach(OperatingSystem val in values)
        {
            operatingSystems.Add(new SelectListItem
            {
                Text = val.ToString(),
                Value = val.ToString()
            });
        }
        return operatingSystems;
    }

    public List<SelectListItem> GetMachineTypes()
    {
        List<SelectListItem> machineTypes = new List<SelectListItem>();
        Array values = Enum.GetValues(typeof(MachineType));
        machineTypes.Add(new SelectListItem
        {
            Text = "Select",
            Value = ""
        });

        foreach (MachineType val in values)
        {
            machineTypes.Add(new SelectListItem
            {
                Text = val.ToString(),
                Value = val.ToString()
            });
        }
        return machineTypes;
    }
}
  

Server.cs

 public class Server
{
    [Key]
    [Required]
    public int Id { get; set; }
    public string Name { get; set; }
    public OperatingSystem OS { get; set; }
    [Display(Name = "Machine Type")]
    public MachineType MachineType { get; set; }
    [Display(Name = "Admin User Name")]
    public string AdminUserName { get; set; }
    [Display(Name = "Admin Password")]
    public string AdminPassword { get; set; }
    [Display(Name = "ESX Host")]
    public string EsxHost { get; set; }
    public int IpAddressId { get; set; }
    [ForeignKey("IpAddressId")]
    public IpAddress IpAddress { get; set; }
}
  

Startup.cs

     Mapper.Initialize(config =>
    {
        config.CreateMap<IpAddressViewModel, IpAddress>().ReverseMap();
        config.CreateMap<ServerViewModel, Server>().ReverseMap();
    });
  

РЕДАКТИРОВАТЬ: после некоторого чтения я обнаружил, что могу добавить .Include() предложение к своему запросу, чтобы ввести IpAddress объект. Мой новый ServersController.cs код приведен ниже. Тем не менее, я все еще немного смущен. Разве это не тот тип вещей, о которых Automapper должен был позаботиться автоматически? Я упускаю весь смысл Automapper?

НОВЫЙ ServersController.cs

 public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var server = Mapper.Map<ServerViewModel>(await _context.Servers.Include(s => s.IpAddress).SingleOrDefaultAsync(m => m.Id == id));

    if (server == null)
    {
        return NotFound();
    }
    return View(server);
}
  

Комментарии:

1. Вы проверяли, является ли _context.Servers.SingleOrDefaultAsync(m => m.Id == id).IpAddress значение null?

2. Пожалуйста, покажите вам сопоставление и убедитесь, что IPAddress не равен null на вашем сервере.

3. @C Sharper это действительно null. Это заставляет меня думать, что я делаю что-то еще неправильно. У меня сложилось впечатление, что Entity Framework будет извлекать IpAddress объект на основе IpAddressId . Я ошибаюсь?

4. @Rabban Я добавил раздел конфигурации mapper из моего Startup.cs. IpAddressId не равен нулю на моем сервере. Это внешний ключ, связывающий обратно с таблицей IPAddress.

5. Для отложенной загрузки IpAddress , чтобы работать, отметьте это свойство как virtual в модели EF.

Ответ №1:

Я собираюсь продолжить и ответить на этот вопрос, чтобы закрыть его.

Ключом было добавление .Include() предложения к моему запросу LINQ для извлечения объектов, прикрепленных к родительскому объекту.

Правильный способ сделать это находится в моем разделе редактирования выше. Другие примеры можно найти здесь .