I have a VERY simple model as seen here:
public class Cases
{
//case data model for call center
//implement lists for all related child tables too
[Key]
public int CasesID { get; set; }
public string CaseNumber { get; set; }
[Required(ErrorMessage = "Customer is Required")]
public int CustomerID { get; set; }
public Customer Customer { get; set; }
[MaxLength(50)]
public string UserName { get; set; } //get user name from the aspnet membership
[Required(ErrorMessage = "Case Category is Required")]
public int CaseCategoryID { get; set; }
[Required(ErrorMessage = "Technician is Required")]
public int TechnicianID { get; set; }
public Technician Technicians { get; set; }
[Required(ErrorMessage = "Engine Model is Required")]
public int EngineModelID { get; set; }
public EngineModel EngineModel { get; set; }
[MaxLength(50)]
public string BMSWorkorder { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Status is Required")]
public string CaseStatus { get; set; }
[MaxLength(50)]
public string OpenedBy { get; set; }
[Required(ErrorMessage = "Opened Date is Required")]
[DataType(DataType.DateTime)]
public DateTime? OpenedDate { get; set; }
[MaxLength(50)]
public string ClosedBy { get; set; }
[DataType(DataType.DateTime)]
public DateTime? ClosedDate { get; set; }
[MaxLength(50)]
[Required(ErrorMessage="Caller First Name is Required")]
public string CallerFirstName { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Caller Last Name is Required")]
public string CallerLastName { get; set; }
[MaxLength(10)]
[Required(ErrorMessage = "Qualified is Required")]
public string Qualified { get; set; }
public string Description { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "ESN is Required")]
public string ESN { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Mileage is Required")]
public string Mileage { get; set; }
[DataType(DataType.Date)]
public DateTime? DateInService { get; set; }
[MaxLength(50)]
public string ESTR { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "EDS is Required")]
public string EDS { get; set; }
[MaxLength(50)]
public string GensetSerialNumber { get; set; }
[MaxLength(50)]
public string GensetModelNumber { get; set; }
//child Case Notes records
public virtual ICollection<CaseNotes> CaseNotes { get; set; }
//child case attachment records
public virtual ICollection<Attachment> Attachments { get; set; }
//child case complaint records
public virtual ICollection<CaseComplaint> CaseComplaint { get; set; }
//tracking fields
public DateTime? CreatedOn { get; set; }
[MaxLength(50)]
public string CreatedBy { get; set; }
public DateTime? ModifiedOn { get; set; }
[MaxLength(50)]
public string ModifiedBy { get; set; }
}
A Case can have many CaseNotes, Attachments, and CaseComplaints. Foreign Keys are Technicians, Customers, and EngineModel.
Up until today, all was well with Add, and Edits with this model. Now, out of the blue I get
“A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.”
only when trying to update a case record on the Edit view. A create and insert is fine since all required fields are filled.
Why would this just start happening. FYI, If I inspect the model just be for I call context.SaveChanges, I notice that all the data looks right, FK values are filled in, however the data in the navigation property for the foreign key class (Technicians) almost seems like it thinks I am trying to insert a new record in those classes…
Here are my controller Edit actions:
public ActionResult Edit(int id)
{
Cases cases = db.Cases.Find(id);
db.Entry(cases).Reference(x => x.Customer).Load();
db.Entry(cases).Collection(x => x.CaseComplaint).Load();
db.Entry(cases).Collection(x => x.CaseNotes).Load();
db.Entry(cases).Reference(x => x.Technicians).Load();
GetCaseCategoryLookup(cases.CaseCategoryID);
GetEngineModelLookup(cases.EngineModelID);
GetTechnicianLookup(cases.TechnicianID);
GetQualifiedList(cases.Qualified);
GetCaseStatusList(cases.CaseStatus);
return View(cases);
}
//
// POST: /Cases/Edit/5
[HttpPost]
public ActionResult Edit(Cases cases)
{
if (ModelState.IsValid)
{
AppHelpers help = new AppHelpers();
if (cases.CaseStatus == "CLOSED")
{
cases.ClosedBy = "USER";
cases.ClosedDate = help.GetEasternTime();
}
cases.ModifiedBy = "USER";
cases.ModifiedOn = help.GetEasternTime();
db.Entry(cases).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
Just to explain what the exception means:
Principal object in your controller post action is
cases.Technicians, the dependent iscases. The “property values that define the referential constraints” are the foreign key in the dependent object, that iscases.TechnicianID, and on the other side the primary key of the principal, that iscases.Technicians.TechnicianID.The exception says that those two values are different:
cases.TechnicianID != cases.Technicians.TechnicianIDbut they must be the same when you update the entity.I don’t know what your view is exactly supposed to do. Can you only edit the
casesentity or also thecases.Techniciansproperties? Or can you only assign a new existing technician tocases? If the latter is the case I’m worndering why the model binder creates acases.Techniciansinstance because there shouldn’t be any form fields that hold properties of thecases.Technicians. To assign another existing technician it should be enough to have the foreign keycases.TechnicianIDbound to a form field.In any case you need to ensure that either
cases.TechnicianIDandcases.Technicians.TechnicianIDhave the same value or thatcases.Techniciansisnull. It depends on what the view is supposed to do and what data you need to update – onlycasesproperties orcases.Techniciansproperties as well.