检索老师使用 C# 和 MySQL 教授的课程

问题描述 投票:0回答:1

我正在开发一个 C# 应用程序,该应用程序与 MySQL 数据库交互,以检索有关教师及其教授的课程的信息。我有一个教师表,其中包含有关教师的信息,还有一个班级表,其中包含有关课程的详细信息,包括与每门课程关联的教师 ID。每个老师可以教授多门课程。

这是我当前的代码:

[HttpGet]
[Route("api/teacherdata/findteacher/{teacherid}")]
public Teacher FindTeacher(int TeacherId)
{
    Teacher NewTeacher = new Teacher();

    MySqlConnection Conn = School.AccessDatabase();
    Conn.Open();
    
    MySqlCommand cmd = Conn.CreateCommand();
    cmd.CommandText = "SELECT * FROM teachers LEFT JOIN classes ON teachers.teacherid = classes.teacherid WHERE teachers.teacherid = @TeacherId;";
    cmd.Parameters.AddWithValue("@TeacherId", TeacherId);
    cmd.Prepare();
    MySqlDataReader ResultSet = cmd.ExecuteReader();

    while (ResultSet.Read()) 
    {
        // Fetch teacher information
        NewTeacher.TeacherId = Convert.ToInt32(ResultSet["teacherid"]);
        NewTeacher.TeacherFname = ResultSet["teacherfname"].ToString();
        // ... (other teacher details)

        // Fetch course information
        NewTeacher.ClassName = ResultSet["classname"].ToString();
        // ... (other course details)
    }

    Conn.Close();
    return NewTeacher;
}

我想修改此方法以包含老师教授的所有课程的列表。我怎样才能实现这个目标?

任何帮助将不胜感激。谢谢!

c# sql mysql visual-studio http-get
1个回答
0
投票

您现有的查询将包含这些信息,但重要的是要了解 SQL 中的 JOIN 将在表之间产生称为笛卡尔积的结果。例如,如果您有 1 位老师负责 2 门课程并加入表格,您将得到 2 个结果行:

TeacherId    TeacherFName   ClassId   CourseName
        1    John                 1   Chemistry
        1    John                 2   Physics

...作为一个简单的示例,因此读取数据的代码需要考虑到这一点,而不是为两行创建两个教师。因此,如果您希望找到通过 ID 加载的单个老师,我会建议如下所示:

public Teacher FindTeacher(int TeacherId)
{
    Teacher? NewTeacher = null;

    // Note: Any class that is Disposable should be disposed. use using.
    using MySqlConnection Conn = School.AccessDatabase(); 
    Conn.Open();
    
    MySqlCommand cmd = Conn.CreateCommand();
    cmd.CommandText = "SELECT * FROM teachers LEFT JOIN classes ON teachers.teacherid = classes.teacherid WHERE teachers.teacherid = @TeacherId;";
    cmd.Parameters.AddWithValue("@TeacherId", TeacherId);
    cmd.Prepare();
    MySqlDataReader ResultSet = cmd.ExecuteReader();

    while (ResultSet.Read()) 
    {
        if (NewTeacher == null) // Populate the teacher on the first row read.
            NewTeacher = new Teacher
            {
                TeacherId = Convert.ToInt32(ResultSet["teacherid"]);
                TeacherFname = ResultSet["teacherfname"].ToString();
                // ...
            };

        // Fetch course information and add to the teacher.
        NewTeacher.Courses.Add(new Course
        {
             ClassName = ResultSet["classname"].ToString();
             // ... (other course details)
        }
    }

    Conn.Close();
    return NewTeacher;
}

这里您的老师最初为空,因此当我们读取第一行时,我们会将与老师相关的详细信息加载到一个新实例中。教师类将包含课程对象的集合来保存课程相关的详细信息。这应该在 Teacher 类中自动初始化为新的

List<Course>

 public ICollection<Course> Courses { get; private set; } = new List<Course>();

现在,当您迭代记录时,您可以为每一行填充课程。

当您连接更多表时,笛卡尔积可能会给查询带来一些重大成本,因为不仅每行中的列数会增加以考虑所有表字段,而且返回的总行数是所有相关行的乘积。一条教师记录可能会导致数十、数百或更多行需要筛选,具体取决于表的连接方式。在许多情况下,拆分查询效率更高。

我建议学习像实体框架这样的 ORM 来处理所有 SQL 和笛卡尔积处理,以读取和更新数据。它可以将这样的方法简化为:

public Teacher FindTeacher(int teacherId)
{
    using var accessDbContext = new AccessDbContext();

    var teacher = accessDbContext.Teachers
        .Include(t => t.Courses)
        .AsNoTracking()
        .Single(t => t.TeacherId == teacherId);
    return teacher;
}

或者,如果您不需要教师和课程的每一列,您可以使用

Select
轻松将其投影到 DTO 或 ViewModel 类,以获取调用者实际需要的列。 (建议不要传递实体类)

© www.soinside.com 2019 - 2024. All rights reserved.