Reputation: 482
I have the Course
entity that holds a collection of Students
, and they are in a Many-to-Many relationship, as per tutorial here.
I can add a Student object with course.Students.Add(student);
, but I cannot remove it with none of the following:
// Using Clear()
course.Students.Clear();
// Manually removing
foreach (var item in course.Students)
{
course.Students.Remove(item);
}
//Forcefully reassign
course.Students = new List<Student>();
Can someone tell me why that is? I tried follow here, but no avail. I think I may have to manually remove it from the join table below, but mine is automatically created so I can't access it.
Course 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; }
}
}
Student 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; }
}
}
My method (azure function)
[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));
}
EDIT 1:
Here are parts of my code-first migration files for the join 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();
});
Upvotes: 0
Views: 534
Reputation: 34978
Did you verify that your course is lazy loading students? If lazy loading is disabled then course.Students will be empty. When modifying the collection of students you should be eager-loading it regardless:
var course = context.Courses
.Include(x => x.Students)
.Single(x => x.CourseId == courseId);
From there you should be able to use:
course.Students.Clear();
since Course.Students will be a proxy that EF recognizes and the Clear method will mark all entries for removal. With many-to-many relationships you may need to dis-associate the course from each of the students:
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();
to be sure that the references are removed in the event that any of the students might be marked as modified.
Lastly, with tracked entities, just call SaveChanges()
rather than calling Update
. Update
is for untracked/detached entities.
Upvotes: 1