读取器关闭时无效尝试调用HasRows

时间:2016-06-06 11:52:22

标签: c# sql

我遇到此问题:关闭阅读器时无效尝试调用HasRows。 我尝试了很多;删除连接关闭线,最后关闭连接。但有同样的问题。我的代码无法解决问题。

try
{
    con = new SqlConnection(ConfigurationManager.ConnectionStrings["TextItConnectionString"].ConnectionString);
    using (con)
    {
        con.Open();
        Library.writeErrorLog("connection build and open");
        SqlCommand cmd = con.CreateCommand();
        using (cmd)
        {
            cmd.CommandText = "Select [name] From [dbo].[Users]";
            SqlDataReader reader = cmd.ExecuteReader();
            using (reader)
            {
                user.dt.Load(reader);
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        Library.writeErrorLog(reader.GetString(0));
                    }
                }
                else
                    Library.writeErrorLog("no rows");
                reader.Close();
                con.Close();
            }
        }
    }
    //SqlDataAdapter adap = new SqlDataAdapter("Select [name] From [dbo].[Users]", con);
    //adap.Fill(user.dt);
}
catch (Exception ex)
{
    Library.writeErrorLog(ex);
}

感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

我认为user.dt会返回DataTable。您知道DataTable.Load(reader)将使用结果集的所有记录并将读者推进到下一组吗?我问,因为您使用HasRows 之后已经使用过DataTable.Load

作为Steve has commented

  

您可以清楚地查看DataTable.Load的参考来源   在退出方法之前看到DataReader已关闭。

因此,如果没有其他结果集(fe SELECT * FROM T1;SELECT* from T2),读者将在Load结束时关闭,如果您尝试使用SqlDataReader.HasRows,则会导致异常。

我称之为缺少文档,因为它在MSDN上没有提及。

所以要么使用

  1. reader.Readreader.GetString在循环中并手动将其添加到DataTable
  2. 使用DataTable.Load然后循环表格或
  3. 使用SqlDataAdapter.Fill(table)
  4. 1)while循环并手动填写表格

    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        if(reader.HasRows)
        {
            while (reader.Read())
            {
                string name = reader.GetString(0);
                user.dt.Rows.Add(name);
                Library.writeErrorLog(name);
            }
        }
        else
            Library.writeErrorLog("no rows");
    }
    

    2)需要两个循环,一个在DataTable.Loadforeach

    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        if(reader.HasRows)
        {
            user.dt.Load(reader); // all records added
            foreach(DataRow row in user.dt.Rows)
            {
                string name = row.Field<string>(0);
                Library.writeErrorLog(name);
            }
        }
        else
            Library.writeErrorLog("no rows");
    }
    

    3)另一种选择是使用SqlDataAdapter及其Fill(dataTable)方法:

    using (var da = new SqlDataAdapter(cmd))
    {
        da.Fill(user.dt);
        if (user.dt.Rows.Count > 0)
        {
            foreach (DataRow row in user.dt.Rows)
            {
                string name = row.Field<string>(0);
                Library.writeErrorLog(name);
            }
        }
        else
            Library.writeErrorLog("no rows");
    }
    

    附注:如果您使用reader.Close语句,则无需使用con.Closeusing