0

I get an error message while trying to update related entity.

When create new one is OK.

The error message say :

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.

Please review my codes, and advice me what I am doing wrong.

First of all, DB is Mysql MyISAM.

Entity Class

[Table("note")]
public class Note
{
    [Key]
    public int id { get; set; }

    [Required(ErrorMessage="Content is required")]
    [DisplayName("Note")]
    public string content { get; set; }
    public DateTime date { get; set; }

    [Required(ErrorMessage = "User ID is required")]
    [DisplayName("User ID")]
    public string userId {get; set;}
    public Boolean isPrivate { get; set; }

    [DisplayName("Attach File")]
    public virtual ICollection<AttachedFile> AttachedFiles { get; set; }

}

[Table("attachedfile")]
public class AttachedFile
{
    [Key]
    public int id { get; set; }
    public int noteId { get; set; }
    public string fileName { get; set; }
}

Controller,

[HttpPost]
public ActionResult Index(Note note, HttpPostedFileBase attFile)
{
    try
    {
    if (ModelState.IsValid)
    {
        updateAttachFile(note, attFile);
        if (note.id > 0)
        {
        unitOfWork.NoteRepository.UpdateNote(note);
        }
        else
        {
        unitOfWork.NoteRepository.InsertNote(note);
        }

        unitOfWork.Save();
        return RedirectToAction("Index");
    }
    }catch(DataException){
    ModelState.AddModelError("", "Unable to save changes. Try again please");
    }

    var notes = unitOfWork.NoteRepository.GetNotes();
    return View(new NoteViewModel() { noteList = notes.ToList(), note = new Note() });
}

private void updateAttachFile(Note note,HttpPostedFileBase attFile)
{
    if (attFile == null) return;

    List<AttachedFile> list;
    if (note.id > 0)
    {
    list = unitOfWork.AttachedFileRepository.Get(filter: q => q.noteId.Equals(note.id)).ToList();
    }
    else
    {
    list = new List<AttachedFile>();
    }

    var fileName = Path.GetFileName(attFile.FileName);
    fileName = fileName.Replace(" ", "");
    fileName = Regex.Replace(fileName, @"\s|\$|\#\%", "");
    var path = Path.Combine(Server.MapPath("~/App_data/uploads"), fileName);
    attFile.SaveAs(path);

    list.Add(new AttachedFile
    {
    fileName = fileName
    });

    note.AttachedFiles = list;
}
}

enter image description here

1 Answer 1

1

By setting the state of note to Modified EF will attach the related entities, especially the newly created AttachedFile, to the context as well, but in state Unchanged. You haven't set the correct foreign key property value though (which is necessary if the entity is not in state Added). Doing this would remove the exception:

list.Add(new AttachedFile
{
    noteId = note.id,
    fileName = fileName
});

But your new AttachedFile won't be added to your database because it's not in Added state.

I would expect that is works if you call updateAttachFile after Update/Insert...

if (note.id > 0)
    unitOfWork.NoteRepository.UpdateNote(note);
else
    unitOfWork.NoteRepository.InsertNote(note);
updateAttachFile(note, attFile);
unitOfWork.Save();

...because change detection happening in SaveChanges will recognize the new entity and put it into Added state automatically.

As a side note: I don't know why you load the existing AttachedFiles with unitOfWork.AttachedFileRepository.Get.... It should work in my opinion with an empty list for both cases Update and Insert.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you very much, now I understand how EF works. I loaded existed data because I thought it will replace with existed data too.^^ May I ask one more question please?, How EF knows Note.id related with AttachedFile.noteId? I didn't define in anywhere and also it is MYISAM that is not available define FK.
For example, I add noteNo field into AttachedFile table and add noteNo variable into entity class too. And I run the application, it work fine, EF didn't confused at all :). Now what if I want I change FK to noteNo not noteID, how should I do this?
@Expertwannabe: About your first comment: EF knows it because it applies certain naming conventions to infer a mapping. In this case: It sees the AttachedFiles collection that refers to the AttachedFile class. Then it looks if in this class is a property with name "Class name of Note + Property Name of PK" (=NoteId, capital and small letters don't matter). And yes, there is one: noteId. Then it assumes that this must be the foreign key property. If you would give it another name like MySpecialId it wouldn't find an FK property and your exception would not occur.
@Expertwannabe: About your second comment: If noteId doesn't represent a foreign key, then yes, it is the easiest solution to rename it.
@Expertwannabe: I meant to rename the property noteId to noteNo or so? Don't you want this? I don't understand the MyIsam thing, why there is no definition of a FK possible. Maybe ask a new question about this problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.