正确的循环SQL查询的方法?

时间:2015-08-19 14:50:04

标签: c# mysql sql-server

我有一个列表,通过传递学生班级列表

来检索学生的成绩 然后,它通过数据库查询学生的姓名来提取学生成绩。这段代码工作正常,但当studentList的大小增加时,这段代码的执行速度很慢,

通过SQL查询循环列表的正确方法是什么?

private List<StudentClass> getStudentGrades(List<StudentClass> studentList)
{
    for (int i =0; i < studentList.Count; i++)
    {
        string sqlcommand = "SELECT StudentGrades FROM Students WHERE StudentName=@StudentName";
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(sqlcommand, conn))
        {
            cmd.Parameters.AddWithValue("@StudentName", studentList[i].StudentName);
            cmd.ExecuteNonQuery();
            SqlDataReader reader = cmd.ExecuteReader();

            while (reader.Reader())
            {
                studentList[i].StudentGrades = int.Parse(reader["StudentGrades"].ToString());
            }
        }
    }

    return studentList;
}

public class StudentClass
{
    public string StudentName {get; set; }
    public int StudentGrades {get; set; }
}

3 个答案:

答案 0 :(得分:5)

首先 - 你不必两次执行你的命令。你首先调用ExecuteNonQuery(因为ExecuteNonQuery没有返回数据,所以它没有任何效果,但是由于请求实际传递给SQL服务器并被执行,它会减慢执行速度)。然后,您正在调用ExecuteReader,您实际上正在从中检索数据。

第二个问题 - 您正在为每个学生执行新查询。因此,如果您将列出1000名学生 - 将执行1000次查询。

首先考虑从数据库获取所有数据,然后相应地更新studentList

首先获取SELECT StudentName, StudentGrades FROM Students,将结果保存到某个词典(或任何您想要的地方),然后循环studentList

答案 1 :(得分:0)

private List<StudentClass> getStudentGrades(List<StudentClass> studentList)
{
    string sqlcommand = "SELECT StudentGrades FROM Students WHERE StudentName=@StudentName";
    var conn = new SqlConnection();
    SqlCommand cmd = new SqlCommand(sqlcommand, conn);
    cmd.Parameters.Add("@StudentName");
    using (conn)
    {
        conn.Open();
        for (int i = 0; i < studentList.Count; i++)
        {
            cmd.Parameters[0].Value= studentList[i].StudentName;
            studentList[i].StudentGrades = (int)cmd.ExecuteScalar();
        }            
    }

    return studentList;
}

注意:您应该在一个查询中检索整个列表,这样会好得多。

答案 2 :(得分:0)

正如其他用户指出的那样,您不需要执行者。

但更大的问题是您的SQL语句一次只返回一个学生的数据。是否还有其他字段可用于选择一组中的所有学生?即,是否存在“类”字段或类似字段,因此您可以执行以下操作:

select studentgrades
  from students
 where class = @class

如果没有,你仍然可以使用in子句编写一种丑陋的sql语句。所以:

select studentgrades
  from studens
 where studentname in ('studentname1', 'studentname2', etc. )

使用这种方法,您可以将代码修改为:

private List<StudentClass> getStudentGrades(List<StudentClass> studentList)
{
        string studentListParam = "";
        foreach(StudentClass student in studentlist)
        {
           // blah blah stuff to only add comma if not first element
           studentListParam = studentListParam + ", '" + student.StudentName + "';
        }

        string sqlcommand = @"
SELECT StudentName, StudentGrades
  FROM Students
 WHERE StudentName in (" + studentlist + ")";
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(sqlcommand, conn))
        {
            cmd.Parameters.AddWithValue("@StudentName", studentList[i].StudentName);
            cmd.ExecuteNonQuery();
            SqlDataReader reader = cmd.ExecuteReader();

            while (reader.Reader())
            {
                StudentClass student = studentList.Where(s => s.StudentName == string.Parse(reader["StudentName"]);
                student.StudentGrades = int.Parse(reader["StudentGrades"].ToString());
            }
        }
    }

    return studentList;
}

public class StudentClass
{
    public string StudentName {get; set; }
    public int StudentGrades {get; set; }
}

显然你需要一些空检查和其他各种错误检查才能使这个生产准备就绪,但这应该是一个起点。

(另请注意,此方法不会尝试对查询进行参数化,因此您会丢失一点解析时间,但是会比使用多个查询丢失的数量少一个数量级。)