【问题标题】:Entity Framework Update related entity实体框架更新相关实体
【发布时间】:2012-10-31 21:34:02
【问题描述】:

我在尝试更新相关实体时收到一条错误消息。

新建一个就OK了。

错误信息说:

发生了参照完整性约束冲突:定义 关系中的主体对象和依赖对象之间的引用约束不一致。

请检查我的代码,并告诉我我做错了什么。

首先,DB是Mysql MyISAM。

实体类

[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; }
}

控制器,

[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;
}
}

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    通过将note 的状态设置为Modified,EF 会将相关实体(尤其是新创建的AttachedFile)附加到上下文中,但状态为Unchanged。但是,您尚未设置正确的外键属性值(如果实体不在状态 Added 中,这是必需的)。这样做会消除异常:

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

    但是您的新AttachedFile 不会添加到您的数据库中,因为它不在Added 状态。

    如果您在更新/插入之后调用 updateAttachFile,我希望这是可行的...

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

    ...因为SaveChanges 中发生的更改检测将识别新实体并自动将其置于Added 状态。

    附带说明:我不知道您为什么使用 unitOfWork.AttachedFileRepository.Get... 加载现有的 AttachedFiles。在我看来,对于 Update 和 Insert 两种情况,它都应该使用空的 list。

    【讨论】:

    • 非常感谢,现在我明白了 EF 的工作原理了。我加载了现有数据,因为我认为它也会替换为现有数据。^^ 请问我可以再问一个问题吗?,EF 如何知道 Note.id 与 AttachedFile.noteId 相关?我没有在任何地方定义,而且它是 MYISAM 无法定义 FK。
    • 例如,我将noteNo字段添加到AttachedFile表中,并将noteNo变量也添加到实体类中。我运行应用程序,它工作正常,EF 一点也不困惑 :)。现在,如果我想将 FK 更改为 noteNo 而不是 noteID,我该怎么做?
    • @Expertwannabe:关于您的第一条评论:EF 知道这一点,因为它应用某些命名约定来推断映射。在这种情况下:它看到引用 AttachedFile 类的 AttachedFiles 集合。然后查看这个类中是否有一个名为“Note 的类名 + PK 的属性名”的属性(=NoteId,大小写无关紧要)。是的,有一个:noteId。然后它假定这必须是外键属性。如果您给它取另一个名称,例如 MySpecialId,它将找不到 FK 属性并且您的异常不会发生。
    • @Expertwannabe:关于您的第二条评论:如果noteId 不代表外键,那么是的,这是最简单的重命名解决方案。
    • @Expertwannabe:我的意思是将属性noteId 重命名为noteNo 左右?你不想要这个吗?我不明白 MyIsam 的事情,为什么没有可能的 FK 定义。也许就这个问题提出一个新问题。
    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多