简体   繁体   English

如果没有剩余要读取的行,请关闭SqlDataReader-C#

[英]Close SqlDataReader if there are no more rows left to read - C#

This is causing me a headache. 这让我头疼。 I know this question (or atleast variants of it) has been asked many times but before one flags it as a duplicate please consider the following code: 我知道这个问题(或它的至少一个变体)已经被问过很多次,但是在将其标记为重复之前,请考虑以下代码:

    string myConnectionString =  myConnectionString = ConfigurationManager.ConnectionStrings["DBCS"].ToString();
     SqlConnection mySQLConnection;
     SqlCommand mySQLCommand;
     SqlDataReader mySQLDataReader;

    using (mySQLConnection = new SqlConnection(myConnectionString))
    {
       mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection);
       mySQLCommand.Connection = mySQLConnection;
       mySQLCommand.Connection.Open();
       using(mySQLDataReader = mySQLCommand.ExecuteReader())
       {
         if (mySQLDataReader.HasRows)
         {
             if (mySQLConnection.State == ConnectionState.Open)
             {
                while (mySQLDataReader.Read())
                {
                  //Perform Logic : If the last record being returned meets some condition then call the below method
                   MethodCalled();
                }            
            }
         }
      }
         MessageBox.Show("Connection state: " + mySQLConnection.State);
   }

I would like to find a way to either: 我想找到一种方法:

  1. Close the reader after it has finished reading 阅读器关闭后,关闭阅读器
  2. Break out of the while-loop when it has finished reading and there are no more rows left 当它完成读取并且没有剩余的行时,退出while-loop

But I just keep on getting a SqlException stating the following: 但是我只是继续获得一个SqlException声明以下内容:

invalid attempt to call read when reader is closed 关闭阅读器时尝试调用read的无效尝试

Just from broad observation, I can trace that error is due to me returning data that contains one row only. 从广泛的观察中,我可以追溯到错误归因于我返回的数据仅包含一行。 The problem is that after it has read that row, the compiler goes back to While(mySQLDataReader.Read()){} and attempts to read through a table that does not contain any rows. 问题在于,在读取该行之后,编译器将返回While(mySQLDataReader.Read()){}并尝试读取不包含任何行的表。

I attempted the following: 我尝试了以下操作:

  1. Wrapping the ExecuteReader() from the command object in a using block so that it automatically closes the reader and the connection respectively once it has done reading like so: 将命令对象的ExecuteReader()包装在using块中,这样一旦完成读取,它将分别自动关闭阅读器和连接,如下所示:

     using(mySQLDataReader = mySQLCommand.ExecuteReader()) { //Logic performed } 
  2. Just before the closing brace of the while-loop , I tried checking if there are any more rows left/returned from the sql command and breaking out the loop once that condition is satisfied: while-loop的结束括号之前 ,我尝试检查sql命令是否还有剩余的行/返回了行,并在满足该条件后中断了循环:

     if(mySQLDataReader.HasRows == false) //No more rows left to read { break; //break out of loop } 

Both attempts were unsuccessful. 两次尝试均未成功。 How can I get around this? 我该如何解决?

It must be one of the following 3 things: 它必须是以下三件事之一:

  1. You're using Read() OUTSIDE the using block. 您正在使用using块之外的Read() Remember that using block will implicitly call Close and Dispose on your reader. 请记住, using block会在您的阅读器上隐式调用CloseDispose Thus any Read() calls must be placed inside the using block. 因此,任何Read()调用都必须放在using块内。
  2. The body of your using block is explicitly closing the reader. using块的主体明确关闭了阅读器。 This seems improbable. 这似乎是不可能的。
  3. Apparently you have declared your mySQLDataReader at a higher level. 显然,您已在更高级别声明了mySQLDataReader It could be that some other (async) code is closing the reader. 可能是其他一些(异步)代码关闭了阅读器。 This also is unlikely. 这也不可能。 You shouldn't, in most cases, define a DataReader at global level. 在大多数情况下,您不应在全局级别定义DataReader

Edit 编辑

Reading the full code block that you have posted now, I'd suggest a few changes. 阅读您现在发布的完整代码块,我建议进行一些更改。 Can you run the following and tell us if it runs: 您可以运行以下命令并告诉我们是否运行该命令:

using (var mySQLConnection = new SqlConnection(myConnectionString))
{
   mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection, mySQLConnection);
   mySQLCommand.Connection.Open();
   using(mySQLDataReader = mySQLCommand.ExecuteReader())
   {
      while (mySQLDataReader.Read())
      {
        //Perform Logic : If the last record being returned meets some condition then call the below method
         MethodCalled();
      }            
   }
}

If this version runs fine, we can then dig the problem better. 如果此版本运行良好,则可以更好地解决问题。

If there is no data to iterate, while loop will not execute at all. 如果没有要迭代的数据,则while循环将根本不会执行。 Do you need to check for HasRows as such? 您是否需要检查HasRows? Also, you should use CommandBehavior.CloseConnection when you are creating data reader. 另外,在创建数据读取器时,应使用CommandBehavior.CloseConnection。 This will make sure that underlying connection is closed once you have read through it. 一旦您通读了基础连接,这将确保其关闭。

Should if call SqlDataReader.HasRows if I am calling SqlReader.Read 如果我正在调用SqlReader.Read,则应该调用SqlDataReader.HasRows

SQLDataReader Source Code SQLDataReader源代码

using (SqlConnection mySQLConnection = new SqlConnection(myConnectionString))
{
using (SqlCommand mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection))
  {
    mySQLConnection.Open();

    SqlDataReader mySQLDataReader = mySQLCommand.ExecuteReader(CommandBehavior.CloseConnection);
     while (mySQLDataReader.Read())
       {
          //Code logic here
        }
        // this call to mySQLDataReader.Close(); will close the underlying connection
         mySQLDataReader.Close();
    }
     MessageBox.Show("Connection state: " + mySQLConnection.State);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM