尝试更新实体框架中的记录 无法更改关系,因为一个或多个外键属性不可为空
本文关键字:一个 属性 因为 框架 实体 更新 记录 关系 | 更新日期: 2023-09-27 18:35:42
我整天都在寻找解决这个问题的方法。仍然没有找到解决方案。
尝试使用实体框架更新数据库中的记录时,我收到此错误。
无法更改关系,因为一个或多个外键属性不可为空。对关系进行更改时,相关的外键属性将设置为 null 值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
public bool PostChangesStudent(Student updatedStudent)
{
// Get current student from the database.
var student = _db.Students.Find(updatedStudent.Id);
if (student != null)
{
// Clear all cources from the ICollection list.
student.Courses.Clear();
foreach (var course in updatedStudent.Courses)
{
// Adds the new edited courses
student.Courses.Add(course);
}
// Save changes in database
_db.Entry(student).State = EntityState.Modified;
_db.SaveChanges();
}
正如错误所描述的那样,我删除了课程列表中的旧课程对象,然后我想应该添加一个新关系吗?我只是不知道下一步该怎么做。
你看到的是我从数据库(学生)中获取(未编辑的)对象,以及我可以使用参数(updateStudent)检索的updateStudent对象。
学生和课程模型
public class Student
{
public int Id { get; set; }
public string StudentNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Courses
public virtual ICollection<Course> Courses{ get; set; }
}
public class Course
{
public int Id { get; set; }
public int StudentId { get; set; }
public string CourseName { get; set; }
public int CourseNumber { get; set; }
}
这是一对多的关系,
我已经使用 Context类和 ContextInitializer 设置了测试数据,我使用本教程解决了这个问题:
实体框架 6 教程
已经阅读了很多关于这个问题的堆栈帖子,但无法理解该怎么办。.
更新
对不起,我打错了字。.我正在使用 clear 从数据库中获取的原始学生对象中取出课程。
然后我循环访问更新的Student.Courses,它由编辑的课程组成,并将它们映射到学生对象中。
完成后,我想再次将对象保存在数据库中,以具有新课程(更新的课程)。
更新2
在与丹路德维希讨论后,我终于把它弄得:D
以下是要执行的操作:
- 像他说的那样删除清除。
从学生对象中清除课程,如下所示:
foreach (var course in student.Courses.ToArray()) { _db.Entry(course).State = EntityState.Deleted; student.Courses.Remove(course); }
循环更新的学生课程并将课程对象添加到学生对象。
foreach (var course in updatedStudent.Courses) { student.Courses.add(course); }
希望这可以帮助其他人解决这个疯狂的错误!
我认为问题可能来自这一行:
student.Courses.Clear();
。因为Course
有 2 个不可为空的外键属性。当您从Student
中清除这些内容时,您正在"更改关系",因此 EF 将尝试将Course.StudentId
设置为 null。它不能。因为它是一个不可为空的外键属性。
你真的想删除这些课程吗?如果是这样,请删除它们,而不是从集合中删除它们(或在上下文中将其状态标记为已删除)。
// student.Courses.Clear(); get rid of this line, it is bad for you
foreach (var course in student.Courses.ToArray())
{
_db.Entry(course).State = EntityState.Deleted;
student.Courses.Remove(course);
}
正如错误所描述的那样,我删除了课程列表中的旧课程对象...
不,您不会在任何地方删除任何内容。在 EF 中,从一对多集合属性中删除项与删除该项不同。即使从student.Courses
集合中删除它们,EF 上下文仍会跟踪这些实体,默认情况下只会尝试将其外键值设置为 null。它不能。因为它是一个不可为空的外键属性。