Ray Suelzer
Ray Suelzer

Reputation: 4107

"EF foreign key (or entity?) not cascading/updating

I am using the WebAPI in MVC4. I have a simple form which submits data to the API via a PUT request. The data arrives and is serialized fine and everything looks wonderful, except that anywhere there is a foreign key is not getting updated. And yes, the foreign key exists.

I have the following classes:

public class TriageRecord
{
    [Key]
    public Int64 PKEY { get; set; }
    public DateTime DateAdded { get; set; }
    public DateTime DateUpdated { get; set; }
    public Int64? RecordSource_Id { get; set; }  
    public Int64? AssignedVolunteer_Id { get; set; }  
    public string FacebookID { get; set; }
    public Int64? VANID { get; set; }
    public Int64? NationBuilderID { get; set; }
    public DateTime? DateVanSubmitted { get; set; }
    public Int64? FollowUpLevel_Id { get; set; } 
    public bool? Complete { get; set; }


    public string First { get; set; }
    public string Mid { get; set; }
    public string Last { get; set; }
    public string Email { get; set; }
    public string Address1 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip5 { get; set; }


    public string HomePhone { get; set; }
    public string CellPhone { get; set; }

    public Int32? EmployeeStatus { get; set; }
    public string StoreNumber { get; set; }
    public virtual WorkArea WorkArea { get; set; }   //put your focus here
    public virtual Department Department { get; set; }
    public virtual Shift Shift { get; set; }


   }

Here is the WorkArea class which I am updating via my form.

public class WorkArea
{
    [Key]
    public Int64 Id { get; set; }
    [StringLength(200)]
    public string WorkAreaName { get; set; }
}

Here is the JSON I am posting which arrives very nicely to my API Controller:

   var saveRecord = function() {
            var record = {
                "PKEY": $("#PKEY").val(),
                "DateAdded": $("#DateAdded").val(),
                "DateUpdated": "@DateTime.Now.ToString()",
                "First": $("#First").val(),
                "Mid": $("#Mid").val(),
                "Last": $("#Last").val(),
                "RecordSource_Id": $("#RecordSource_Id").val(),
                "AssignedVolunteer_Id": $("#AssignedVolunteer_Id").val(),
                "FacebookID": $("#FacebookID").val(),
                "VANID": $("#VANID").val(),
                "NationBuilderID": $("#NationBuilderID").val(),
                "DateVanSubmitted": Date.now(),
                "FollowUpLevel_Id": $("#FollowUpLevel_Id").val(),
                "Complete": $("#Complete").val(),
                "Email": $("#Email").val(),
                "Address1": $("#Address1").val(),
                "City": $("#City").val(),
                "State": $("#State").val(),
                "Zip5": $("#Zip5").val(),
                "HomePhone": $("#HomePhone").val(),
                "CellPhone": $("#CellPhone").val(),
                "EmployeeStatus": $("#EmployeeStatus").val(),
                "StoreNumber": $("#StoreNumber").val(),
                "WorkArea": {
                    "Id": 1,
                    "WorkAreaName": "GM"
                },
                "Department": $("#Department").val(),
                "Shift": $("#Shift").val()                       
            };

It is serialized and it arrives to my controller where I can see when I set my breakpoint that the WorkArea (Models.WorkArea) is populated with Id = 1 & WorkAreaName = "GM"

So this is my controller:

  public HttpResponseMessage PutTriageRecord(long id, TriageRecord triagerecord)
    {
        if (id == triagerecord.PKEY)  //breakpoint here shows triagerecord contains workarea values
        {                
            db.Entry(triagerecord).State = EntityState.Modified;                
            try
            {                    
            db.SaveChanges();  //changes get saved for everything (ie, first name) but not workarea...
            }
            catch (DbUpdateConcurrencyException)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }
    }

Everything is updated in my TriageRecord except for WorkArea... Why?

Update: NOT WORKING. This is what I added to my controller... it just keeps creating a ton of entires in the WorkAreas table.

  public HttpResponseMessage PutTriageRecord(long id, TriageRecord triagerecord)
    {
        if (id == triagerecord.PKEY)  //breakpoint here shows triagerecord contains workarea values
        {                
            db.Entry(triagerecord).State = EntityState.Modified;                
            try
            {      
                db.TriageRecords.Attach(triagerecord);   //attach
                db.Entry(triagerecord.WorkArea).State = EntityState.Added;   //add           
            db.SaveChanges();  //WORKS!
            }
            catch (DbUpdateConcurrencyException)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }
    }

Upvotes: 1

Views: 2121

Answers (1)

user1878526
user1878526

Reputation:

You need to call Attach and set the state of the child objects to Added. It doesn't have anything to do with WebApi, this is how EF works when you are working with detached objects (e.g. when you send them out to client side and back). The db context track's the changes so it won't know what has been added modified automatically when you work with detached objects.

"If you don't call Attach the children stay detached until SaveChanges is called where EF will assume that they are new entities (because they are not attached to the context) and set their state to Added. Then they will be inserted into the database."

EF 4.3 CF does not update relationships when saving changes

Upvotes: 1

Related Questions