Entity Framework: 为什么我不能在这种多对多关系中清空一个集合?
Entity Framework: Why can I not empty a collection in this Many-to-Many relations?
我有 Course
实体,它包含 Students
的集合,并且它们处于多对多关系中,按照教程 here。
我可以使用 course.Students.Add(student);
添加学生对象,但我不能使用以下 none 删除它:
// Using Clear()
course.Students.Clear();
// Manually removing
foreach (var item in course.Students)
{
course.Students.Remove(item);
}
//Forcefully reassign
course.Students = new List<Student>();
谁能告诉我这是为什么?我尝试关注 here,但无济于事。我想我可能必须从下面的连接 table 中手动删除它,但我的是自动创建的,所以我无法访问它。
联合tableCourseStudent
课程class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Library
{
public class Course
{
public Course()
{
this.Students = new HashSet<Student>();
}
public string CourseId { get; set; }
public string CourseName { get; set; }
public string Department {get; set;}
public virtual ICollection<Student> Students { get; set; }
}
}
学生class
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Library
{
public class Student
{
public Student()
{
this.Courses = new HashSet<Course>();
}
public string StudentId { get; set; }
[Required]
public string StudentName { get; set; }
public int Age { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
}
我的方法(天蓝色函数)
[FunctionName("UpdateCourse")]
public async Task<IActionResult> UpdateCourse(
[HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "courses/{CourseId}")]
HttpRequest req,
ILogger log, string CourseId) {
var course = await _context.Courses.FindAsync(CourseId);
// course.Students.Clear();
foreach (var item in course.Students)
{
course.Students.Remove(item);
}
_context.Update(course);
await _context.SaveChangesAsync();
return new OkObjectResult(removeSelfReference(course));
}
编辑 1:
这是我的部分代码优先迁移文件,用于加入 table CourseStudent
20220415034607_M1.cs:
migrationBuilder.CreateTable(
name: "CourseStudent",
columns: table => new
{
CoursesCourseId = table.Column<string>(type: "nvarchar(450)", nullable: false),
StudentsStudentId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CourseStudent", x => new { x.CoursesCourseId, x.StudentsStudentId });
table.ForeignKey(
name: "FK_CourseStudent_Courses_CoursesCourseId",
column: x => x.CoursesCourseId,
principalTable: "Courses",
principalColumn: "CourseId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CourseStudent_Students_StudentsStudentId",
column: x => x.StudentsStudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
});
20220415034607_M1.Designer.cs:
modelBuilder.Entity("CourseStudent", b =>
{
b.HasOne("Library.Course", null)
.WithMany()
.HasForeignKey("CoursesCourseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Library.Student", null)
.WithMany()
.HasForeignKey("StudentsStudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
您是否确认您的课程正在延迟加载学生?如果禁用延迟加载,则 course.Students 将为空。修改学生集合时,你应该 eager-loading 无论如何:
var course = context.Courses
.Include(x => x.Students)
.Single(x => x.CourseId == courseId);
从那里你应该可以使用:
course.Students.Clear();
因为 Course.Students 将成为 EF 识别的代理,并且 Clear 方法将标记所有条目以进行删除。对于 many-to-many 关系,您可能需要 dis-associate 每个学生的课程:
var course = context.Courses
.Include(x => x.Students)
.Single(x => x.CourseId == courseId);
foreach(var student in course.Students)
student.Courses.Remove(course);
course.Students.Clear();
context.SaveChanges();
确保在任何学生可能被标记为已修改的情况下删除引用。
最后,对于被跟踪的实体,只需调用 SaveChanges()
而不是调用 Update
。 Update
适用于 untracked/detached 个实体。
我有 Course
实体,它包含 Students
的集合,并且它们处于多对多关系中,按照教程 here。
我可以使用 course.Students.Add(student);
添加学生对象,但我不能使用以下 none 删除它:
// Using Clear()
course.Students.Clear();
// Manually removing
foreach (var item in course.Students)
{
course.Students.Remove(item);
}
//Forcefully reassign
course.Students = new List<Student>();
谁能告诉我这是为什么?我尝试关注 here,但无济于事。我想我可能必须从下面的连接 table 中手动删除它,但我的是自动创建的,所以我无法访问它。
联合tableCourseStudent
课程class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Library
{
public class Course
{
public Course()
{
this.Students = new HashSet<Student>();
}
public string CourseId { get; set; }
public string CourseName { get; set; }
public string Department {get; set;}
public virtual ICollection<Student> Students { get; set; }
}
}
学生class
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Library
{
public class Student
{
public Student()
{
this.Courses = new HashSet<Course>();
}
public string StudentId { get; set; }
[Required]
public string StudentName { get; set; }
public int Age { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
}
我的方法(天蓝色函数)
[FunctionName("UpdateCourse")]
public async Task<IActionResult> UpdateCourse(
[HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "courses/{CourseId}")]
HttpRequest req,
ILogger log, string CourseId) {
var course = await _context.Courses.FindAsync(CourseId);
// course.Students.Clear();
foreach (var item in course.Students)
{
course.Students.Remove(item);
}
_context.Update(course);
await _context.SaveChangesAsync();
return new OkObjectResult(removeSelfReference(course));
}
编辑 1:
这是我的部分代码优先迁移文件,用于加入 table CourseStudent
20220415034607_M1.cs:
migrationBuilder.CreateTable(
name: "CourseStudent",
columns: table => new
{
CoursesCourseId = table.Column<string>(type: "nvarchar(450)", nullable: false),
StudentsStudentId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CourseStudent", x => new { x.CoursesCourseId, x.StudentsStudentId });
table.ForeignKey(
name: "FK_CourseStudent_Courses_CoursesCourseId",
column: x => x.CoursesCourseId,
principalTable: "Courses",
principalColumn: "CourseId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CourseStudent_Students_StudentsStudentId",
column: x => x.StudentsStudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
});
20220415034607_M1.Designer.cs:
modelBuilder.Entity("CourseStudent", b =>
{
b.HasOne("Library.Course", null)
.WithMany()
.HasForeignKey("CoursesCourseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Library.Student", null)
.WithMany()
.HasForeignKey("StudentsStudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
您是否确认您的课程正在延迟加载学生?如果禁用延迟加载,则 course.Students 将为空。修改学生集合时,你应该 eager-loading 无论如何:
var course = context.Courses
.Include(x => x.Students)
.Single(x => x.CourseId == courseId);
从那里你应该可以使用:
course.Students.Clear();
因为 Course.Students 将成为 EF 识别的代理,并且 Clear 方法将标记所有条目以进行删除。对于 many-to-many 关系,您可能需要 dis-associate 每个学生的课程:
var course = context.Courses
.Include(x => x.Students)
.Single(x => x.CourseId == courseId);
foreach(var student in course.Students)
student.Courses.Remove(course);
course.Students.Clear();
context.SaveChanges();
确保在任何学生可能被标记为已修改的情况下删除引用。
最后,对于被跟踪的实体,只需调用 SaveChanges()
而不是调用 Update
。 Update
适用于 untracked/detached 个实体。