实体框架不会更新外键对象 [英] Entity Framework does not update Foreign Key object
问题描述
我是新来的实体框架和这种行为混淆了我:
[表(ClinicProfile)]
公共类ClinicProfile
{
[关键]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)
公众诠释标识{搞定;组; }
[ForeignKey的(联络资料)]
公众诠释ContactDataId {搞定;组; }
公共联络资料联络资料{搞定;组; }
}
表(联络资料)]
公共类联络资料
{
[关键]
[DatabaseGenerated(DatabaseGeneratedOption。身份)
公众诠释标识{搞定;组; }
:
}
当插入新实体一切工作正常 - 联络资料保存到表并指定外键:
clinicProfile.ContactData =联络资料;
SharedContext.Current.Entry(clinicProfile).STATE = EntityState.Added;
SharedContext.Current.SaveChanges();
但是,当我尝试更新这个实体,联络资料没有得到更新。
clinicProfile.ContactData =联络资料;
SharedContext.Current.Entry(clinicProfile).STATE = EntityState.Modified;
SharedContext.Current.SaveChanges();
我必须标记为修改的联络资料吗? ?还是我做错了什么。
修改 - 2 - 答案
使用此代码,如果联络人资料为DB中的新对象,新对象ID。
clinicProfile.ContactData =联络资料;
SharedContext.Current.Entry(clinicProfile).STATE = EntityState.Modified;
SharedContext.Current.SaveChanges();
如果你只是想更新旧的联络资料,这将是正确使用此代码:
SharedContext.Current.Entry(联络资料).STATE = EntityState.Modified;
SharedContext.Current.SaveChanges();
修改 - 扩展代码的快照
$从MVC控制器,回发从页。b $ b
代码。参数clinicProfile和联络资料,adressData包含有效标识的。
[HttpPost]
[ValidateAntiForgeryToken]
公众的ActionResult修改(ClinicProfile clinicProfile,联络资料联络资料,AdressData adressData)
{
ViewBag.Id = clinicProfile.Id;
如果(ModelState.IsValid)
{
如果(clinicProfile.Id!= 0)
{
clinicProfile.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);
返回查看(新ClinicProfileComposite {AdressData = adressData,ClinicProfile = clinicProfile,联络资料=联络资料});
}
{
clinicProfile.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);
返回RedirectToAction(信息,新{ID = clinicProfile.Id});
}
}
ViewBag.Id = clinicProfile.Id;
返回查看(新ClinicProfileComposite {AdressData = adressData,ClinicProfile = clinicProfile,联络资料=联络资料});
}
您刚刚放错位置的外键财产
[表(ClinicProfile)]
公共类ClinicProfile
{
[键]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)
公众诠释标识{搞定;组; }
// [ForeignKey的(联络资料)]这里错了地方
公众诠释ContactDataId {搞定;组; }
[ForeignKey的(ContactDataId)] //这里的正确位置
公共联络资料联络资料{搞定;组; }
}
表(联络资料)]
公共类联络资料
{
[关键]
[DatabaseGenerated(DatabaseGeneratedOption。身份)
公众诠释标识{搞定;组; }
:
}
和当你想设置外键的数据,您可以设置ContactDataId值或从数据库作为对象检索联络资料,并将其设置在ClinicProfile
//根据发布的数据后
[HttpPost]
[ValidateAntiForgeryToken]
公众的ActionResult修改(ClinicProfile clinicProfile,联络资料联络资料,adressData adressData)
{
ViewBag.Id = clinicProfile.Id;
如果(ModelState.IsValid)
{
如果(clinicProfile.Id!= 0)//这里要告诉SharedContext
{
到联络资料附加到clinicProfile
//你需要从分贝
VAR检索联络资料的lastVersion currentContactData = SharedContext.Current.ContactData.Single(T => t.Id = contactData.Id) ;
//更新的currentContactData
clinicProfile.ContactData = currentContactData更改后的数据; //而不是联络资料;
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);
返回查看(新ClinicProfileComposite {AdressData = adressData,ClinicProfile = clinicProfile,联络资料=联络资料});
}
{
clinicProfile.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);
返回RedirectToAction(信息,新{ID = clinicProfile.Id});
}
}
ViewBag.Id = clinicProfile.Id;
返回查看(新ClinicProfileComposite {AdressData = adressData,ClinicProfile = clinicProfile,联络资料=联络资料});
}
//为注释讨论的结果。
如果您想更新联络资料,你需要告诉联络资料是由它的状态设置为修改和你在过去的文章中提到,如果你把下面这将工作修改背景:
SharedContext.Current.Entry(clinicProfile).STATE = EntityState.Modified; SharedContext.Current.Entry(联络资料).STATE = EntityState.Modified; SharedContext.Current.SaveChanges();
希望这会帮助你。
I'm new to Entity Framework and this behavior confuses me:
[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; }
...
}
When inserting the new entity all works fine - ContactData is saved to the table and foreign key assigned:
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Added;
SharedContext.Current.SaveChanges();
But when I try to update this entity, ContactData don't get an update.
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
Must I mark ContactData as modified too? Or am I just doing something wrong?
EDIT-2 - The answer
Use this code, if contactData is the new object in the DB, with the new object id.
clinicProfile.ContactData = contactData;
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
If you just want to update the old contactData, it would be correct to use this code:
SharedContext.Current.Entry(contactData).State = EntityState.Modified;
SharedContext.Current.SaveChanges();
EDIT - extended code snapshot
Code from MVC controller, postback from the page. Parameters "clinicProfile" and "contactData", "adressData" contain valid Id's.
[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 });
}
you just misplaced the foreign key property
[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; }
...
}
and when you want to set the foreign key data, you can either set the ContactDataId value or retrieve the ContactData from Database as object and set it in the 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 });
}
// as result of comments discussion
if you want to update contactData , you need to tell the context that contactData was modified by setting its state to modified and as you mentioned in your last post, it will work if you make the following:
SharedContext.Current.Entry(clinicProfile).State = EntityState.Modified; SharedContext.Current.Entry(contactData).State = EntityState.Modified; SharedContext.Current.SaveChanges();
hope that this will help you
这篇关于实体框架不会更新外键对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!