1

Я новичок в мире MVC и EF. Сначала я нацелен на MVC 4 EF 5, используя код.Редактирование/просмотр нескольких моделей в одном представлении

Я ищу наилучшую практику для редактирования двух связанных моделей, используя один вид. Для простоты я следующие две модели:

namespace AddressBook.Models 
{ 
    public class Contact 
    { 
     public int ID { get; set; } 
     public string First_Name { get; set; } 
     public string Last_Name { get; set; } 
     public List<PhoneNumber> PhoneNumbers { get; set; } 
    } 
} 

и

namespace AddressBook.Models 
{ 
    public class PhoneNumber 
    { 
     public int ID { get; set; } 
     public string Number { get; set; } 
     public bool Primary { get; set; } 
    } 
} 

со следующим контекстом:

using System.Data.Entity; 
namespace AddressBook.Models 
{ 
    public class DataContext : DbContext 
    { 
     public DbSet<Contact> Contacts { get; set; } 
     public DbSet<PhoneNumber> PhoneNumbers { get; set; } 
    } 
} 

Взаимосвязь между контактом и PhoneNumber является один ко многим, однако я хотел бы иметь возможность редактировать first_name, last_name и Number, если для Primary установлено значение true, поэтому мы будем редактировать только один номер телефона на запись контакта.

Я видел похожие сообщения, которые указывают на использование ViewModel, но только примеры моделей просмотра, которые я видел, используются, когда они используются вместо представления, когда вы передаете информацию для выпадающего списка.

Я думаю, у меня есть несколько вопросов:

  1. бы ViewModel выглядеть, как показано ниже?

    public class ContactPrimaryNumberViewModel 
    { 
        public Contact ContactToEdit {get; set;} 
        public PhoneNumber PhoneNumberToEdit {get;set;} 
    } 
    
  2. Что бы отредактировали (опубликовали) и отредактировали (получите)?

Любая помощь будет оценена, чтобы помочь мне обернуть мою голову вокруг этого ...

здесь Редактировать (получить) модифицированное для поддержки, если контакт не имеет телефонный номер, связанный

'// GET:/Контактная информация/Редактировать/5

public ActionResult Edit(int id = 0) 
    { 
     ContactPrimaryNumberViewModel ContactPrimaryNumber = (from pn in db.PhoneNumbers 
                   where pn.ContactID == id && pn.Primary == true 
                   select new ContactPrimaryNumberViewModel { ContactID = pn.ContactID, First_Name = pn.Contact.First_Name, Last_Name = pn.Contact.Last_Name, Number = pn.Number }).SingleOrDefault(); 



     if (ContactPrimaryNumber == null) 
     { 
      ContactPrimaryNumber = (from c in db.Contacts 
                    where c.ID == id 
                    select new ContactPrimaryNumberViewModel { ContactID = c.ID, First_Name = c.First_Name, Last_Name = c.Last_Name, Number = null }).Single(); 

     } 
     return View(ContactPrimaryNumber); 
    }' 

поэтому окончательное решение после всяких помощь:

модели:

public class PhoneNumber 
{ 
    public int ID { get; set; } 
    public string Number { get; set; } 
    public bool Primary { get; set; } 

    [Required] 
    public int ContactID { get; set; } 
    public Contact Contact { get; set; } 

} 

    public class Contact 
{ 
    public int ID { get; set; } 
    public string First_Name { get; set; } 
    public string Last_Name { get; set; } 
    public List<PhoneNumber> PhoneNumbers { get; set; } 


} 

контроллер редактировать (получить и ро й)

 // GET: /Contact/Edit/5 

    public ActionResult Edit(int id = 0) 
    { 

     ContactPrimaryNumberViewModel ContactPrimaryNumber = (from c in db.Contacts 
                   join pn in db.PhoneNumbers 
                   on c.ID equals pn.ContactID into outer 
                   from _pn in outer.Where(p => p.Primary ==true).DefaultIfEmpty() 
                   where c.ID == id 
                   select new ContactPrimaryNumberViewModel { ContactID = c.ID, First_Name = c.First_Name, Last_Name = c.Last_Name, Number = ((_pn == null) ? "" : _pn.Number) }).FirstOrDefault(); 

     if (ContactPrimaryNumber == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(ContactPrimaryNumber); 
    } 

    // POST: /Contact/Edit/5 

    [HttpPost] 
    public ActionResult Edit(ContactPrimaryNumberViewModel ContactPrimaryNumber) 
    { 
     Contact c = db.Contacts.Find(ContactPrimaryNumber.ContactID); 
     PhoneNumber pn = db.PhoneNumbers.FirstOrDefault(x => x.ContactID == ContactPrimaryNumber.ContactID && x.Primary == true); 

     if (ModelState.IsValid) 
     { 
      c.First_Name = ContactPrimaryNumber.First_Name; 
      c.Last_Name = ContactPrimaryNumber.Last_Name; 

      if (pn == null) //if there is no phone number associated with the contact in the DB 
      { 
       if (!String.IsNullOrEmpty(ContactPrimaryNumber.Number)) 
       { 
        //Add a new phonenumber in the database 

        PhoneNumber Px = new PhoneNumber(); 

        Px.ContactID = ContactPrimaryNumber.ContactID; 
        Px.Number = ContactPrimaryNumber.Number; 
        Px.Primary = true; 

        db.PhoneNumbers.Add(Px); 

       } 

      } 
      else //if there is a phone number associated with the contactin the DB 
      { 
       if (String.IsNullOrEmpty(ContactPrimaryNumber.Number)) 
       { 
        //delete the existing number 
        db.PhoneNumbers.Remove(pn); 

       } 
       else 
       { 
        //modify the existing number 
        pn.Number = ContactPrimaryNumber.Number; 
       } 
      } 


      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(c); 
    } 

и ViewModel

public class ContactPrimaryNumberViewModel 
{ 

    public int ContactID { get; set; } 
    public string First_Name { get; set; } 
    public string Last_Name { get; set; } 
    public string Number { get; set; } 


} 

еще раз спасибо за вашу помощь

+0

Прежде всего вам нужен контактный внешний ключ в PhoneNumber, тогда вы можете создать собственный способ сохранения. Я напишу его в нескольких – Komengem

+0

Привет, Коменге ... спасибо за ответ ...Я просто заметил внешний ключ, когда я попытался сгенерировать scafolding, и он не создал viewbag для меня автоматически, как сейчас выглядит «public class PhoneNumber { public int ID {get; задавать; } public string Number {get; задавать; } public bool Primary {get; задавать; } [Обязательно] public int ContactID {get; задавать; } public Контакт Контакт {get; задавать; } } ' – user2129585

+0

Mhmm Еще один вопрос, прежде чем я напишу вам мой ответ, почему контакт должен иметь несколько номеров? Это действительно необходимо? – Komengem

ответ

0

Я думаю, ваша модель вид должен выглядеть следующим образом:

public class ContactPrimaryNumberViewModel 
{ 
    public int ID { get; set; } 
    public string First_Name { get; set; } 
    public string Last_Name { get; set; } 
    public string Number { get; set; } 
} 

И ваше обновление будет выглядеть что-то вроде:

Contact c = context.Contacts.Find(id); 
PhoneNumber p = context.PhoneNumbers 
    .FirstOrDefault(x => x.id == id && x.Primary == true); 
//validate input 
//update as necessary 
//SaveChanges() etc... 

от вашего комментария - вы новый вверх модель класса ContactPrimaryNumberViewModel:

var ContactPrimaryNumber = 
    from pn in db.PhoneNumbers 
    where pn.ContactID == id && pn.Primary == true 
    select new ContactPrimaryNumberViewModel() { 
     ContactID = pn.ContactID, 
     First_Name = pn.Contact.First_Name, 
     Last_Name = pn.Contact.Last_Name, 
     Number = pn.Number 
    }; 
+0

Привет, qujck ... thanks для вашего ответа ... Я думаю, обновив ваше указание на редактирование [HttpPost], что бы отредактировало (get) выглядеть не так, как там, где мне нужно связать свои модели с viewmodel – user2129585

+0

, это стандартный проекционный запрос, в котором создается экземпляр ContactPrimaryNumberViewModel – qujck

+0

вот путь, по которому я начал идти прошлой ночью, это то, что я использую «var ContactPrimaryNumber = from pn in db.PhoneNumbers где pn.ContactID == id && pn.Primary == true select new {ContactID = pn.ContactID, First_Name = pn.Contact.First_Name, Last_Name = pn.Contact.Last_Name, Number = pn.Number}; ', но я получаю сообщение об ошибке: ** Невозможно неявно преобразовать тип' System.Linq.IQueryable '** Я думаю, что я понимаю ошибку, которую я пытаюсь присвоить анонимному типу, который был создан проекцией для моего типа вейвмодели. Однако я не знаю, что делать, чтобы исправить это. – user2129585

0

Хорошо, попробуйте следующее:

PhoneNumber

public class PhoneNumber 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Number { get; set; } 
    public bool Primary { get; set; } 

    [ForeignKey("Contact"), DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int? ContactId { get; set; } 

    public virtual Contact Contact { get; set; } 
} 

Контакт

public class Contact 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ContactId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public List<PhoneNumber> PhoneNumbers { get; set; } 
} 

SaveContact: в зависимости от того, как вы настроили свои Хранилища или класс Ef. Это может зайти в вашу реализацию EfRepository или ваш класс EfDb.

public void SavePlayer(Contact contact) 
    { 
     using (var context = new EfDb()) 
     {     
      if (contact.ContactId == 0) 
      {      
       context.Contacts.Add(contact); 
      } 
      else if (contact.ContactId > 0) 
      { 
       var currentContact = context.Contacts 
        .Include(c => c.PhoneNumber) 
        .Single(c => c.ContactId== contact.ContactId); 

       context.Entry(currentContact).CurrentValues.SetValues(contact); 
       currentContact.PhoneNumber= contact.PhoneNumber; 
      } 
      context.SaveChanges(); 
     } 
    } 

Редактировать действие

[HttpGet] 
    public ActionResult Edit(int id) 
    { 
     var contact= _dataSource.Contacts.FirstOrDefault(c => c.Id == id); 

     return View(player); 
    } 

    [HttpPost] 
    public ActionResult Edit(Contact contact) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       _dataSource.SaveContact(contact); 
       return RedirectToAction("About", "Home"); 
      } 
     } 
     catch (Exception) 
     { 
      ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); 
     }    
     return View(contact); 
    } 

Просмотров

В вашем Contact View Folder добавить EditorTemplates folder. Затем Scaffold a Create Strongly Typed PhoneNumber Partial View to this folder и назовите его PhoneNumber, как и его модель.

Эшафот Create Strongly Typed Contact View имя его Create

Затем добавьте @Html.EditorFor(model => model.PhoneNumber) к мастеру Create View.

+0

@KomengeMwadila: Спасибо. Я пытаюсь это сейчас – user2129585

+0

@KomengeMwadila: Я следил за вами до создания частичного представления во вновь созданной папке EditorTemplates. потерял меня в «Contact View name it Create», где я должен добавить это представление, это не то же самое, что Create/edit/... У меня уже есть генерация scafolding – user2129585

+0

@KomengeMwadila: когда я добавляю @ Html.EditorFor (model => model.PhoneNumber) в Create View for Contact, по праву заявляет, что PhoneNumber не является частью модели, переданной ему – user2129585

Смежные вопросы