【问题标题】:SqlDataReader returns only one rowSqlDataReader 只返回一行
【发布时间】:2020-06-08 17:25:01
【问题描述】:

我正在使用SqlDataReader 从存储过程中获取数据。即使正在获取记录,while (reader.Read()) 也只会执行一次,因此在我的列表中只添加了一行。

List<Student> tablelist = new List<Student>();

using (SqlConnection con = new SqlConnection(connectionString))
{
    using (SqlCommand cmd = new SqlCommand("SP_ReadPromotedStudents"))
    {
        cmd.Connection = con;
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = Data[0];
        cmd.Parameters.Add("@Email", SqlDbType.VarChar).Value = Data[1];
        cmd.Parameters.Add("@Class", SqlDbType.VarChar).Value = Data[2];

        con.Open();

        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.HasRows)
            {
                 while (reader.Read())
                 {
                     tablelist.Add(new Student
                                    {
                                        Name = (string)(reader[0]),
                                        Email = (string)(reader[1]),
                                        Class = (string)(reader[2]),
                                    });
                     reader.NextResult();
                 }
             }
         }
     }
}

return tablelist;

我的Student班级:

public class Student
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Class { get; set; }
}

我获取了大约 46 条记录。但是在列表中只添加了一条记录。这里有什么错误?

【问题讨论】:

  • 你为什么使用 NextResult ?
  • NextResult() 移动到下一个结果集,而不是下一行。把它拿出来。
  • 如果没有 NextResult(),它将进入无限 while 循环。它卡在 while (reader.Read())
  • 你不应该在阅读器 HasRows 时循环,你应该使用if 而不是while

标签: c# sql-server sqldatareader datareader


【解决方案1】:

您需要在reader.Read() 循环之外将您的呼叫移至NextResult。否则在第一次读取代码后遇到NextResult 调用并尝试加载存储过程返回的第二组数据。

另外HasRows 上的循环是一个无限循环。如果属性reader.HasRows 为真,那么当您读完行时它也为真。

using (SqlDataReader reader = cmd.ExecuteReader())
{
    while (reader.Read())
    {
        tablelist.Add(new Student
        {
            Name = (string)(reader[0]),
            Email = (string)(reader[1]),
            Class = (string)(reader[2]),
        });
    }

    // This should be called only if your stored procedure returns 
    // two or more sets of data otherwise you can remove everything
    reader.NextResult();

    // If there is another set of data then you can read it with a
    // second while loop with
    while(reader.Read())
    {
        .....
    }
}

【讨论】:

  • if(!reader.HasRows()) return; 应添加为using 块之后的切口。您将更快地释放资源并防止下游不可避免的NullReferenceException 错误
【解决方案2】:

理想的情况是有一个新的 sql 语句来得到你想要的,而不是得到一个列表并且只需要第一次访问。想象一下,如果您有一个包含数百万条记录的表,您是否需要执行查询来获取所有记录并只读取第一条记录?不,你执行一个查询来获得你需要的。

DataReader 中的 NextResult 方法将指针移动到下一个结果(如果结果上有)。删除它。

在您更改 sql 语句以获得所需内容后,您将循环结果集。您可以只阅读第一行(将while 更改为if):

if (reader.Read())
{
   tablelist.Add(new Student
   {
     Name = (string)(reader[0]),
     Email = (string)(reader[1]),
     Class = (string)(reader[2]),
   });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    相关资源
    最近更新 更多