繁体   English   中英

更新联结表中的数据

[英]update data in the junction table

ASP.Net Core 与 MySQL

Student 表和 Course 表与联结表 StudentCourse 连接:

Student      StudentCourse       Course
=========    ============        =======
PK | ID      FK | StudentID       PK | ID
   | Name    FK | CourseID           | Name

学生更改了他的课程,因此经理需要更改连接表 StudentCourse 中的 CourseID。

但由于以下原因,我无法直接访问联结表:

public class AppDbContext
{
    public DbSet<CourseModel> CourseModels { get; set; }
    public DbSet<StudentModel> StudentModels { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<StudentCourse>()
            .HasKey(t => new { t.StudentId, t.CourseId });

        builder.Entity<StudentCourse>()
            .HasOne(sc => sc.Student)
            .WithMany(s => s.StudentCourse)
            .HasForeignKey(sc => sc.StudentId);

        builder.Entity<StudentCourse>()
            .HasOne(sc => sc.Course)
            .WithMany(s => s.StudentCourse)
            .HasForeignKey(sc => sc.CourseId);
    }
}

所以我不能直接执行这个 SQL 命令:

UPDATE StudentCourse SET CourseId = '9A414E30-DA37-48ED-105E-08D8129A967A' WHERE StudentId = 'A1F38C12-AE65-464C-C489-08D814F4CDDC'

我想我必须使用内部联接。 我的逻辑是:

    [HttpGet]
    public IActionResult ChangeCourse(Guid id)
    {
        IQueryable<CourseModel> courses = courseModel.GetCourses();
        ViewBag.Courses = new SelectList(courses, "Id", "Name");

        var course = courseModel.GetCourseById(id);

        return View(course);
    }

    [HttpPost]
    public IActionResult ChangeCourse(CourseModel newCourse)
    {
        // I know student's id, so I can get his old course id
        Guid oldCourseId = (from ... in ...).SingleOrDefault();
        // Then just change and save
        oldCourseId = newCourse.Id;
        context.SaveChanges();

        return RedirectToAction();
    }

我有 SQL 命令来获取旧课程 ID:

SELECT CourseId FROM StudentModels L
INNER JOIN StudentCourse R
ON L.Id = R.StudentId
WHERE L.Id = 'A1F38C12-AE65-464C-C489-08D814F4CDDC'

所以问题是:

  1. 我的假设正确吗?
  2. 如何在 LINQ 中编写此 SQL 命令?

我试过了,但得到了 ID 列表:

from student in context.StudentModels join cours in context.CourseModels on student.Id equals studentId select cours.Id

我还不擅长 LINQ。 请帮忙。

学生和课程之间似乎存在多对多的关系。 每个学生都遵循零个或多个课程,每个课程都跟随零个或多个学生。 这就是为什么你需要一个接线表

你写了:

一个学生改变他的课程

好吧,由于学生可以学习几门课程,你不能说学生改变了他的课程。 您可以说学生学习了一门新课程,和/或停止学习另一门课程。

如果您遵循实体框架约定,您将拥有类似于以下的类:

class Student
{
    public int Id {get; set;}
    ...

    // Every Student follows zero or more Courses (many-to-many)
    public virtual ICollection<Course> Courses {get; set;}
}

class Course
{
    public int Id {get; set;}
    ...

    // Every Course is followed by zero or more Courses (many-to-many)
    public virtual ICollection<Student> Students {get; set;}
}

这是检测多对多关系所需的所有实体框架。 它会自动为您创建一个联结表,并在需要时使用它。

如果要更改实体框架中的任何项目,则必须获取完整的项目,并为相关的 Collections 使用Include

停止学习课程并开始学习新课程:

int studentId = ...
int courseIdToStop = ...
int courseIdToAttend = ...

// get the student to change; include his courses
Student studentToChange = dbContext.Students
    .Include(student => student.Courses)
    .Where(student => student.Id == studentId)
    .FirstOrDefault();


// Stop the course
Course courseToStop = studentToChange.Courses
    .Where(course => course.Id == courseIdToStop)
    .FirstOrDefault();

if (courseToStop != null)
{
    // This Student follows this cours; stop it:
    studentToChange.Courses.Remove(courseToStop);
}

Course courseToStart = dbContext.Courses
    .Where(course => course.Id == courseIdToStart)
    .FirstOrDefault();

// only start the course if course exists and not already following
if (courseToStart != null && !studentToChange.Courses.Contains(courseToStart))
{
    studentToChange.Courses.Add(courseToStart);
}

dbContext.SaveChanges();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM