ASP. NET MVC CORE - отношения "многие ко многим" - создание представлений - PullRequest
0 голосов
/ 07 августа 2020

Итак, у меня есть ситуация, когда у меня есть отношение «многие ко многим» между двумя объектами. В центре есть поля, характеризующие отношение. Я упрощу ситуацию с помощью следующего примера (выделено жирным шрифтом простое поле, которое находится между двумя объектами:

public class Hobby
{
    public int HobbyID                            {get;set;}
    public string Name                            {get;set;}
    public string Type                            {get;set;}
    public ICollection<PersonHobby> PersonHobbies {get;set;}
}

public class Person
{
    public int PersonID                           {get;set;}
    public int Age                                {get;set;}
    public string Name                            {get;set;}
    public ICollection<PersonHobby> PersonHobbies {get;set;}
}

public class PersonHobby
{
    public int PersonHobbyID                      {get;set;}
    public int PersonID                           {get;set;}
    public int HobbyID                            {get;set;}
    **public int Rating                             {get;set;}**
}

Какова моя цель? Создать форму, которая позволяет мне создавать человека и сразу же атрибут рейтинг одного или нескольких хобби. Форма создания должна отображать поля ввода для всех доступных хобби, но при отправке должны храниться только поля с данными.

Мне нужна помощь, чтобы понять, как лучше всего этого добиться. До сих пор я пробовал использовать Person Create View и Controller, чтобы показать все хобби в форме. Я сделал это, загрузив все хобби и инициализировав их пустыми в контроллере создания. Но при отправке я получаю такие ошибки, как: «Сложные типы, привязанные к модели, не должны быть абстрактными или типами значений и должны иметь конструктор без параметров».

Спасибо.

1 Ответ

2 голосов
/ 07 августа 2020

Небольшая рекомендация для начала: я бы использовал модели представлений вместо классов сущностей в ваших представлениях, так как это обеспечит вам большую гибкость и поможет вам достичь ваших целей, не начиная загрязнять ваши представления кодом, который там не принадлежит. Вы могли бы, очевидно, сделать это со своими классами сущностей, хотя и внесли некоторые изменения, но я бы не рекомендовал это.

Вы получаете ошибку, я полагаю, потому что вы пытаетесь привязать к своей сущности классы, которые определяют свойства ICollection , а связыватель модели не имеет возможности определить конкретный тип, который следует использовать для их создания. Для быстрого исправления вы можете изменить свой ICollection на конкретный тип, например Collection или List . Но опять же, это первая моя рекомендация ...

Итак, чтобы сделать это правильно, вот что я бы сделал:

public class PersonViewModel
{
   public int Age {get;set;}
   public string Name {get;set;}
   public List<HobbyViewModel> Hobbies {get;set;}
}

public class HobbyViewModel
{
  public int HobbyID {get;set;}
  public string Name {get;set;}
  public string Type {get;set;}
  public int? Rating {get;set;}
}

public class PersonController
   : Controller
{
   ...

   [HttpGet]
   public IActionResult Create()
   {
      PersonViewModel viewModel = new PersonViewModel();
      viewModel.Hobbies = this.DbContext.Hobbies.Select(h => new HobbyViewModel() { Name = h.Name, Type = h.Type }).ToList();
      return this.View(viewModel);
   }

   [HttpPost]
   public IActionResult Create(PersonViewModel model)
   {
      if(!this.ModelState.IsValid)
         return this.BadRequest(model);
      Person person = new Person(){ Age = model.Age, Name = model.Name };
      foreach(HobbyViewModel hobbyViewModel in model.Hobbies)
      {
        //Check if the user has rated the hobby and if not, skip it
        if(!hobbyViewModel.Rating.HasValue)
          continue;
        person.PersonHobbies.Add(new PersonHobby(){ HobbyId = hobbyViewModel.HobbyId, Rating = hobbyViewModel.Rating.Value });
      }
      this.DbContext.Persons.Add(person);
      this.DbContext.SaveChanges();
      return this.RedirectToAction(nameof(Index));
   }
}

Другими словами, в вашем лице form, отобразите форму для каждого из увлечений, представленных в модели представления, с вводом Рейтинг. Когда пользователь публикует форму, проверьте все предоставленные хобби, чтобы проверить, оценил ли его пользователь (ie: проверьте, установлено ли свойство Rating, допускающее значение NULL), и, если да, добавьте новый PersonHobby в результирующую сущность Person. Вуаля!

Наконец, несколько рекомендаций по вашим моделям сущностей:

  • Забудьте об утомительных PersonHobbies именах свойств. Это не повсеместный , и вы всегда должны стремиться к повсеместному распространению, когда это возможно : это делает ваш код красивее, проще для понимания и, следовательно, проще в сопровождении. Назовите свои свойства «Хобби» для сущности «Человек» и, например, «Лица или избиратели» для сущности «Хобби». конфигурация и / или аннотация данных. Более того, я ожидаю, что свойство Person Id будет ... ну, идентификатором Person. Нет необходимости указывать это.
  • Я настаиваю, чтобы облегчить вашу жизнь, забудьте об использовании ваших типов сущностей в представлениях или, что еще хуже, в качестве возвращаемых типов Json / Xml. Вы должны использовать модели представлений для своих представлений и объекты передачи данных (DTO) для возвращаемых типов Json / Xml. Даже если эта концепция может показаться go противоречащей принципу KISS, поверьте мне, это не так. Со временем это просто упростит вашу жизнь, даже если поначалу это может показаться бессмысленной проблемой. Фактически, ваши типы сущностей, вероятно, будут со временем развиваться, а ваши представления - нет, и наоборот. Кроме того, для ваших представлений обычно требуется больше или отличная информация, чем для типов ваших сущностей, и, продолжая следовать этому пути, вы можете обнаружить, что начинаете объединять свои представления с вызовами и т. Д., Тогда как он должен просто содержать view logi c. Вызовы должны выполняться в действиях ваших контроллеров, и они должны заполнять модели всеми данными / информацией, необходимыми для ваших представлений.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...