Entity framework 实体框架更新相关实体
我在尝试更新相关实体时收到错误消息 当创建一个新的是确定的 错误消息显示: 发生引用完整性约束冲突:定义 关系中的主体对象和从属对象之间的引用约束不一致 请检查我的代码,并告诉我我做错了什么。 首先,DB是Mysql MyISAM 实体类Entity framework 实体框架更新相关实体,entity-framework,Entity Framework,我在尝试更新相关实体时收到错误消息 当创建一个新的是确定的 错误消息显示: 发生引用完整性约束冲突:定义 关系中的主体对象和从属对象之间的引用约束不一致 请检查我的代码,并告诉我我做错了什么。 首先,DB是Mysql MyISAM 实体类 [Table("note")] public class Note { [Key] public int id { get; set; } [Required(ErrorMessage="Content is required")]
[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; }
}
[表(“注释”)]
公开课堂讲稿
{
[关键]
公共int id{get;set;}
[必需(ErrorMessage=“内容是必需的”)]
[显示名称(“注释”)]
公共字符串内容{get;set;}
公共日期时间日期{get;set;}
[必需(ErrorMessage=“需要用户ID”)]
[显示名称(“用户ID”)]
公共字符串用户标识{get;set;}
公共布尔值isPrivate{get;set;}
[显示名称(“附加文件”)]
公共虚拟ICollection附件文件{get;set;}
}
[表(“附件”)]
公共类附件文件
{
[关键]
公共int id{get;set;}
public int noteId{get;set;}
公共字符串文件名{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;
}
}
[HttpPost]
公共操作结果索引(注意,HttpPostedFileBase attFile)
{
尝试
{
if(ModelState.IsValid)
{
updateAttachFile(注意,attFile);
如果(note.id>0)
{
unitOfWork.NoteRepository.UpdateNote(注释);
}
其他的
{
unitOfWork.NoteRepository.InsertNote(note);
}
unitOfWork.Save();
返回操作(“索引”);
}
}捕获(数据异常){
ModelState.AddModelError(“,”无法保存更改。请重试”);
}
var notes=unitOfWork.notepository.GetNotes();
返回视图(新的NoteViewModel(){noteList=notes.ToList(),note=new note()});
}
私有void updateAttachFile(注意,HttpPostedFileBase attFile)
{
如果(attFile==null)返回;
名单;
如果(note.id>0)
{
list=unitOfWork.AttachedFileRepository.Get(filter:q=>q.noteId.Equals(note.id)).ToList();
}
其他的
{
列表=新列表();
}
var fileName=Path.GetFileName(attFile.fileName);
fileName=fileName.Replace(“,”);
fileName=Regex.Replace(文件名@“\s\124;\$\ 124;\\\\%,”);
var path=path.Combine(Server.MapPath(“~/App\u data/uploads”),文件名);
attFile.SaveAs(路径);
列表。添加(新附件文件
{
fileName=文件名
});
note.AttachedFiles=列表;
}
}
通过将
注释的状态设置为修改的EF将相关实体,尤其是新创建的附件文件
,也附加到上下文中,但状态为不变。但是,您尚未设置正确的外键属性值(如果实体未处于状态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…
加载现有的附件文件。在我看来,对于更新和插入这两种情况,它都应该是空的列表。非常感谢,现在我了解了EF的工作原理。我加载了现有数据,因为我认为它也将替换为现有数据。^我可以再问一个问题吗?EF如何知道Note.id与AttachedFile.noteId相关?我没有在anywhere中定义,而且MYISAM不可用于定义FK。例如,我将noteNo字段添加到AttachedFile表中,并将noteNo变量添加到entity类中。我运行了这个应用程序,它运行得很好,EF一点也不困惑:)。现在,如果我想将FK改为noteNo而不是noteID,我应该怎么做?@Expertwannabe:关于你的第一条评论:EF知道这一点,因为它应用某些命名约定来推断映射。在本例中:它看到引用AttachedFile
类的AttachedFile
集合。然后查看该类中是否有名为“Note的类名+PK的属性名”(=NoteId
,大写和小写字母无关紧要)的属性。是的,有一个:noteId
。然后它假定这必须是外键属性。如果您给它另一个名称,如MySpecialId
,它将找不到FK属性,也不会发生异常。@Expertwannabe:关于您的第二个注释:如果noteId
不代表外键,则是,重命名它是最简单的方法。@Expertwannabe:我的意思是将属性noteId
重命名为noteNo
左右?你不想要这个吗?我不明白MyIsam的事,为什么没有FK的定义。也许会问一个关于这个问题的新问题。