2014-10-26 3 views
2

Я новичок в Entity Framework и такое поведение меня смущает:Entity Framework не обновляет внешние ключи объекта

[Table("ClinicProfile")] 
    public class ClinicProfile 
    { 
     [Key] 
     [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
     public int Id { get; set; } 

     [ForeignKey("ContactData")] 
     public int ContactDataId { get; set; } 
     public ContactData ContactData { get; set; } 
    } 

    [Table("ContactData")] 
    public class ContactData 
    { 
     [Key] 
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int Id { get; set; } 

     ... 
    } 

При установке новой сущности все работает отлично - КонтактныеДанный сохраняются в таблицу и внешний ключ, назначенной :

clinicProfile.ContactData = contactData; 
SharedContext.Current.Entry(clinicProfile).State = EntityState.Added; 
SharedContext.Current.SaveChanges(); 

Но когда я пытаюсь обновить этот объект, ContactData не получает обновления.

clinicProfile.ContactData = contactData; 
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 

Должен ли я пометить ContactData как измененный тоже? Или я просто делаю что-то неправильно?

EDIT-2 - Ответ

Используйте этот код, если КонтактныеДанные новый объект в БД, с новым ИД объекта.

clinicProfile.ContactData = contactData; 
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 

Если вы хотите обновить старую КонтактныеДанные, было бы правильно использовать этот код:

SharedContext.Current.Entry(contactData).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 

EDIT - расширенный снимок кода

кода от контроллера MVC, обратной передачи со страницы. Параметры «clinicProfile» и «contactData», «adressData» содержат действительные идентификаторы.

 [HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Modify(ClinicProfile clinicProfile, ContactData contactData, AdressData adressData) 
     { 
      ViewBag.Id = clinicProfile.Id; 

      if (ModelState.IsValid) 
      { 
       if (clinicProfile.Id != 0) 
       { 
        clinicProfile.ContactData = contactData; 
        clinicProfile.AdressData = adressData; 
        clinicProfile.AdressDataComposed = adressData.ComposeData(); 
        clinicProfile.ContactDataComposed = contactData.ComposeData(); 

        SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
        SharedContext.Current.SaveChanges(); 

        Config.SaveClinicPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 
        Config.SaveClinicPreviewPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 

        return View(new ClinicProfileComposite { AdressData = adressData, ClinicProfile = clinicProfile, ContactData = contactData }); 
       } 

       { 
        clinicProfile.ContactData = contactData; 
        clinicProfile.AdressData = adressData; 
        clinicProfile.AdressDataComposed = adressData.ComposeData(); 
        clinicProfile.ContactDataComposed = contactData.ComposeData(); 

        SharedContext.Current.Entry(clinicProfile).State = EntityState.Added; 
        SharedContext.Current.SaveChanges(); 

        Config.SaveClinicPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 
        Config.SaveClinicPreviewPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 

        return RedirectToAction("Info", new { id = clinicProfile.Id }); 
       } 
      } 

      ViewBag.Id = clinicProfile.Id; 
      return View(new ClinicProfileComposite { AdressData = adressData, ClinicProfile = clinicProfile, ContactData = contactData }); 
     } 
+0

нормально, сначала вы должны извлечь КонтактныеДанный из базы данных, внести изменения в измененных поля, а затем проверить, если clinicprofile contactdataId же, как contactData.Id => ничего сделать еще изменения clinnicProfile.ContactDataId к новому КонтактныеДанным .Id – Monah

ответ

2

вы просто неуместны ключ собственности иностранного

[Table("ClinicProfile")] 
    public class ClinicProfile 
    { 
     [Key] 
     [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
     public int Id { get; set; } 

     //[ForeignKey("ContactData")] here the wrong place 
     public int ContactDataId { get; set; } 
     [ForeignKey("ContactDataId")] // here the correct place 
     public ContactData ContactData { get; set; } 
    } 

    [Table("ContactData")] 
    public class ContactData 
    { 
     [Key] 
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int Id { get; set; } 

     ... 
    } 

и когда вы хотите установить внешние данные ключа, вы можете либо установите значение ContactDataId, либо извлеките ContactData из базы данных в качестве объекта и установите его в файле ClinicProfile

// according to your data posted later 

[HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Modify(ClinicProfile clinicProfile, ContactData contactData, AdressData adressData) 
     { 
      ViewBag.Id = clinicProfile.Id; 

      if (ModelState.IsValid) 
      { 
       if (clinicProfile.Id != 0) 
       { 
        // here you want to tell the SharedContext to attach the contactData to the clinicProfile 
        // you need to retrieve the lastVersion of contactData from db 
        var currentContactData=SharedContext.Current.ContactData.Single(t=>t.Id=contactData.Id); 
        // update the changed data in the currentContactData 
        clinicProfile.ContactData =currentContactData; // instead of contactData; 
        clinicProfile.AdressData = adressData; 
        clinicProfile.AdressDataComposed = adressData.ComposeData(); 
        clinicProfile.ContactDataComposed = contactData.ComposeData(); 

        SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
        SharedContext.Current.SaveChanges(); 

        Config.SaveClinicPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 
        Config.SaveClinicPreviewPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 

        return View(new ClinicProfileComposite { AdressData = adressData, ClinicProfile = clinicProfile, ContactData = contactData }); 
       } 

       { 
        clinicProfile.ContactData = contactData; 
        clinicProfile.AdressData = adressData; 
        clinicProfile.AdressDataComposed = adressData.ComposeData(); 
        clinicProfile.ContactDataComposed = contactData.ComposeData(); 

        SharedContext.Current.Entry(clinicProfile).State = EntityState.Added; 
        SharedContext.Current.SaveChanges(); 

        Config.SaveClinicPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 
        Config.SaveClinicPreviewPhoto(clinicProfile.ClinicImageUpload, clinicProfile.Id); 

        return RedirectToAction("Info", new { id = clinicProfile.Id }); 
       } 
      } 

      ViewBag.Id = clinicProfile.Id; 
      return View(new ClinicProfileComposite { AdressData = adressData, ClinicProfile = clinicProfile, ContactData = contactData }); 
     } 

// в результате комментариев обсуждения

, если вы хотите обновить КонтактныеДанные, вы должны сказать, что контекст КонтактныеДанные был модифицирован путем установки в состояние модифицирована и, как вы упомянули в своем последнем посту, он будет если вы делаете следующее:

SharedContext.Current.Entry (clinicProfile) .State = EntityState.Modified; SharedContext.Current.Entry (contactData) .State = EntityState.Modified; SharedContext.Current.SaveChanges();

надеюсь, что это поможет вам

+0

Я был уверен, что это была проблема, поэтому я изменил код и повторно сгенерировал базу данных, но поведение остается неизменным :( –

+0

can вы добавляете еще один код, показывающий весь процесс обновления, который вы пытаетесь сделать? – Monah

+0

Добавлена ​​полная версия метода обновления. –

0

Вам просто нужно установить ContactDataId, при обновлении

clinicProfile.ContactData = contactData; 
clinicProfile.ContactDataId = contactData.Id; 
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 
+0

Да, он установлен, а также идентификатор в объекте ContactData. Когда я меняю любой из этих двух идентификаторов, он вызывает для меня исключение конфликта, но все же не обновляет свойства ContactData, если идентификаторы совпадают и действительны. –

+0

Какое исключение оно бросает вам, можете ли вы поместить более подробную информацию? – Monah

+0

«Нарушение ограничения ссылочной целостности: значения свойств, которые определяют ссылочные ограничения, несовместимы между главными и зависимыми объектами в отношении». Если идентификаторы действительны, он ничего не делает (в целях обновления дочернего объекта) –

0

, если вы установите на существующий ClinicProfile новый КонтактныеДанные вы должны сначала сохранить новые КонтактныеДанные к БД, второй получить новый Id и третье обновление ClinicProfile с новым ContactDataId.

clinicProfile.ContactDataId = newContactData.Id; 
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 

Если вы хотите обновить существующие свойства ContactData, то вы должны сохранить только это.

SharedContext.Current.Entry(existingContactData).State = EntityState.Modified; 
SharedContext.Current.SaveChanges(); 
+0

В случае вставить код ниже будет работать: "clinicProfile.ContactData = КонтактныеДанные; SharedContext.Current.Entry (clinicProfile) .State = EntityState.Added; SharedContext.Current.SaveChanges();" –

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