C#SqlDataReader只检索一行

问题描述 投票:2回答:2

我有一个问题,我有超过100名学生的名单,但读者只检索表中的最后一名学生。

string selectQuery = "SELECT * FROM Students WHERE firstName = @first AND lastName = @last";

using (SqlCommand sqlCommand = new SqlCommand(selectQuery, sqlConnection))
{
    sqlCommand.Parameters.Add("@first", SqlDbType.VarChar);
    sqlCommand.Parameters.Add("@last", SqlDbType.VarChar);

    foreach (Student student in studentList)
    {
        sqlCommand.Parameters["@first"].Value = student.first;
        sqlCommand.Parameters["@last"].Value = student.last;
    }

    using (SqlDataReader sqlReader = sqlCommand.ExecuteReader())
    {
        while (sqlReader.Read())
        {
            Console.WriteLine(sqlReader["firstName"].ToString());
            Console.WriteLine(sqlReader["lastName"].ToString());
        }
    }
}
c# sql-server
2个回答
2
投票

如果要检索所有学生的值,则需要在foreach Student循环中执行SQL:

string selectQuery = "SELECT * FROM Students WHERE firstName = @first AND lastName = @last";

using (SqlCommand sqlCommand = new SqlCommand(selectQuery, sqlConnection))
{
    sqlCommand.Parameters.Add("@first", SqlDbType.VarChar);
    sqlCommand.Parameters.Add("@last", SqlDbType.VarChar);

    foreach (Student student in studentList)
    {
        sqlCommand.Parameters["@first"].Value = student.first;
        sqlCommand.Parameters["@last"].Value = student.last;

        using (SqlDataReader sqlReader = sqlCommand.ExecuteReader())
        {
             while (sqlReader.Read())
             {
                 Console.WriteLine(sqlReader["firstName"].ToString());
                 Console.WriteLine(sqlReader["lastName"].ToString());
             }
        }
    }
}

但这真的没有多大意义......你真正想要实现的是什么?您按名字和姓氏搜索 - 您从studentList提供 - 但是您也只输出您检索到的名字和姓氏 - 这与您传入的名称相同 - 那么为什么要进入数据库呢?

更新:正如@PatrickArtner正确评论 - 创建和处理100个SqlDataReader实例并不理想。将这个选择过程粘贴到一个存储过程中会更好,这个过程包含一个SELECT和一个table-valued parameter,它将保存100(或更多)学生ID或信息,根据您的学生ID或信息选择您的学生,然后迭代使用单个SqlDataReader对象从C#中的存储过程得到的结果集。


0
投票

问题的原因是您反复覆盖单个2个参数。查看代码中的注释:

string selectQuery = "SELECT * FROM Students WHERE firstName=@first and lastName=@last";
using (SqlCommand sqlCommand = new SqlCommand(selectQuery, sqlConnection))
{
    sqlCommand.Parameters.Add("@first", SqlDbType.VarChar);
    sqlCommand.Parameters.Add("@last", SqlDbType.VarChar);
    foreach (Student student in studentList) // addds 100 students
    {
        // overwrites the same parameter again and again.... so its only the last one
        sqlCommand.Parameters["@first"].Value = student.first;
        sqlCommand.Parameters["@last"].Value = student.last;
    }

    using (SqlDataReader sqlReader = sqlCommand.ExecuteReader()) 
    {// the query uses only 2 params so you need to change the query and the adding
        while (sqlReader.Read())
        {
            Console.WriteLine(sqlReader["firstName"].ToString());
            Console.WriteLine(sqlReader["lastName"].ToString());
        }
    }
 } 

解决方案使用一个查询搜索所有这些查询,使用来自您的数据的更复杂的WHERE条件构建以及您的数据所需的更多SqlParameters:

// create all the variable names
var firstVarName = Enumerable.Range(1, studentList.Count)
    .Select(i => $"@first_{i}")
    .ToList();
var lastVarName = Enumerable.Range(1, studentList.Count)
    .Select(i => $"@last_{i}")
    .ToList();

var cond = "firstName = {0} and lastName = {1}";

var whereOred = new StringBuilder("WHERE 1 = 0  -- false, just ease of formatting\n");

for (int i = 0; i < firstVarName.Count; i++)
{
    whereOred.AppendLine("   OR " + string.Format(cond, firstVarName[i], lastVarName[i]));
}

// adapt query to search all variable names
string selectQuery = $@"
SELECT *
FROM Students
{whereOred.ToString()}";

Console.WriteLine(selectQuery);
using (SqlCommand sqlCommand = new SqlCommand(selectQuery, sqlConnection))
{
    // add all the variable names with values from studentList
    for(int i=0;i<studentList.Count;i++) 
    {
        sqlCommand.Parameters.Add(firstVarName[i], SqlDbType.VarChar);
        sqlCommand.Parameters.Add(lastVarName[i], SqlDbType.VarChar);
        sqlCommand.Parameters[firstVarName[i]].Value = studentList[i].first;
        sqlCommand.Parameters[lastVarName[i]].Value = studentList[i].last;
    }

    using (SqlDataReader sqlReader = sqlCommand.ExecuteReader())
    { 
        if (sqlReader.HasRows)
            while (sqlReader.Read())
            {
                Console.WriteLine(sqlReader["firstName"].ToString());
                Console.WriteLine(sqlReader["lastName"].ToString());
            }
        else Console.WriteLine("No match.");
    }
}

为我的demodata创建的SqlStatement:

SELECT *
FROM Students
WHERE 1 = 0  -- false, just ease of formatting
   OR firstName = @first_1 and lastName = @last_1
   OR firstName = @first_2 and lastName = @last_2
   OR firstName = @first_3 and lastName = @last_3
   OR firstName = @first_4 and lastName = @last_4
   OR firstName = @first_5 and lastName = @last_5
   OR firstName = @first_6 and lastName = @last_6
   OR firstName = @first_7 and lastName = @last_7
   OR firstName = @first_8 and lastName = @last_8
   OR firstName = @first_9 and lastName = @last_9
   OR firstName = @first_10 and lastName = @last_10
   OR firstName = @first_11 and lastName = @last_11
   OR firstName = @first_12 and lastName = @last_12
   OR firstName = @first_13 and lastName = @last_13
   OR firstName = @first_14 and lastName = @last_14
   OR firstName = @first_15 and lastName = @last_15
   OR firstName = @first_16 and lastName = @last_16
   OR firstName = @first_17 and lastName = @last_17
   OR firstName = @first_18 and lastName = @last_18
   OR firstName = @first_19 and lastName = @last_19
   OR firstName = @first_20 and lastName = @last_20

添加了SqlParameters以执行我的demodata:paramlist in debug mode

我用了

public class Student { public string first; public string last; }

var studentList = Enumerable.Range(1, 20)
    .Select(i => new Student { first = $"firstname {i}", last = $"lastname {i}" })
    .ToList();

创建一些演示学生列表。

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