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() 而不是调用 UpdateUpdate 适用于 untracked/detached 个实体。