且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

实体框架不会更新外键对象

更新时间:2023-02-13 15:14:29

您刚刚放错位置的外键财产

  [表(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