简体   繁体   English

实体框架不更新外键对象

[英]Entity Framework does not update Foreign Key object

I'm new to Entity Framework and this behavior confuses me: 我是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; }

         ...
    }

When inserting the new entity all works fine - ContactData is saved to the table and foreign key assigned: 插入新实体时一切正常 - ContactData保存到表中并分配了外键:

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. 但是当我尝试更新此实体时,ContactData不会获得更新。

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

Must I mark ContactData as modified too? 我是否必须将ContactData标记为已修改? Or am I just doing something wrong? 或者我只是做错了什么?

EDIT-2 - The answer EDIT-2 - 答案

Use this code, if contactData is the new object in the DB, with the new object id. 如果contactData是数据库中的新对象,则使用此代码,并使用新的对象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: 如果您只想更新旧的contactData,那么使用此代码是正确的:

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

EDIT - extended code snapshot 编辑 - 扩展代码快照

Code from MVC controller, postback from the page. 来自MVC控制器的代码,从页面回发。 Parameters "clinicProfile" and "contactData", "adressData" contain valid Id's. 参数“clinicProfile”和“contactData”,“adressData”包含有效的Id。

        [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 当您要设置外键数据时,可以设置ContactDataId值或从Database中检索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 });
        }

// 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: 如果你想更新contactData,你需要通过将其状态设置为修改来告诉contactData被修改的上下文,正如你在上一篇文章中提到的那样,如果你做了以下工作,它将会起作用:

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

hope that this will help you 希望这会对你有所帮助

You just need to set ContactDataId , when updating 您只需在更新时设置ContactDataId

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

if you set to existing ClinicProfile new ContactData you should first save new ContactData to db, second get its new Id and third update ClinicProfile with new ContactDataId. 如果你设置为现有的ClinicProfile新的ContactData,你应该首先将新的ContactData保存到db,第二次获取新的Id和第三次使用新的ContactDataId更新ClinicProfile。

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

if you want to update existing ContactData properties then you should save only it. 如果要更新现有的ContactData属性,则应仅保存它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM