Ich bin neu im Entity Framework und dieses Verhalten verwirrt mich:
[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; }
...
}
Beim Einfügen der neuen Entität funktioniert alles einwandfrei - ContactData wird in der Tabelle und dem zugewiesenen Fremdschlüssel gespeichert:
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Added;
SharedContext.Current.SaveChanges();
Wenn ich versuche, diese Entität zu aktualisieren, erhält ContactData kein Update.
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
Muss ich ContactData auch als geändert markieren? Oder mache ich nur etwas falsch?
EDIT-2 - Die Antwort
Verwenden Sie diesen Code, wenn contactData das neue Objekt in der Datenbank mit der neuen Objekt-ID ist.
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
Wenn Sie nur die alten contactData aktualisieren möchten, ist es richtig, diesen Code zu verwenden:
SharedContext.Current.Entry(contactData).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
BEARBEITEN - erweiterter Code-Snapshot
Code vom MVC-Controller, Postback von der Seite. Die Parameter "clinicProfile" und "contactData", "adressData" enthalten gültige Ids.
[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 });
}
Sie haben gerade die Fremdschlüsseleigenschaft verlegt
[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; }
...
}
Wenn Sie die Fremdschlüsseldaten festlegen möchten, können Sie entweder den ContactDataId-Wert festlegen oder die ContactData-Daten aus der Datenbank als Objekt abrufen und im ClinicProfile festlegen
// 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 });
}
// als Ergebnis der Kommentardiskussion
Wenn Sie ContactData aktualisieren möchten, müssen Sie dem Kontext mitteilen, dass ContactData geändert wurde, indem Sie den Status auf "Modified" setzen. Wie Sie in Ihrem letzten Beitrag erwähnt haben, funktioniert es, wenn Sie Folgendes tun:
SharedContext.Current.Entry (clinicProfile) .State = EntityState.Modified; SharedContext.Current.Entry (contactData) .State = EntityState.Modified; SharedContext.Current.SaveChanges ();
Ich hoffe, das wird dir helfen
Wenn Sie auf bestehende ClinicProfile neue ContactData einstellen, sollten Sie zuerst die neuen ContactData in db speichern, zweitens die neue ID und das dritte Update ClinicProfile mit der neuen ContactDataId abrufen.
clinicProfile.ContactDataId = newContactData.Id;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
Wenn Sie vorhandene ContactData-Eigenschaften aktualisieren möchten, sollten Sie sie nur speichern.
SharedContext.Current.Entry(existingContactData).State = EntityState.Modified;
SharedContext.Current.SaveChanges();