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

时间:2017-09-05 09:04:21

标签: c# winforms ado.net

这让我很头疼。我知道这个问题(或它的至少变种)已被多次询问,但在一个标记为重复之前请考虑以下代码:

    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);
   }

我想找到一种方法:

  1. 阅读完
  2. 后关闭阅读器
  3. while-loop完成阅读并且不再有行
  4. 时,将其中断。{li>

    但我只是继续SqlException说明以下内容:

      

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

    仅仅从广泛的观察,我可以追踪到错误是由于我返回仅包含一行的数据。问题是,在读取该行之后,编译器返回While(mySQLDataReader.Read()){}并尝试读取不包含任何行的表。

    我尝试了以下内容:

    1. ExecuteReader()块中的命令对象中包装using,以便它一旦完成读取就会自动关闭阅读器和连接:

      using(mySQLDataReader = mySQLCommand.ExecuteReader())
      {
          //Logic performed
      }
      
    2. 在<{1}}的右括号之前,我尝试检查sql命令是否还有剩余/返回的行,并在该条件下断开循环很满意:

      while-loop
    3. 两次尝试均未成功。我怎么能绕过这个?

2 个答案:

答案 0 :(得分:3)

必须是以下三件事之一:

  1. 您正在Read()区域外using使用using。请注意,Close阻止会隐式调用您的阅读器上的DisposeRead()。因此,任何using调用都必须放在using块内。
  2. mySQLDataReader块的正文明确关闭了读者。这似乎不太可能。
  3. 显然,您已将DataReader声明为更高级别。可能是其他一些(异步)代码关闭了读者。这也不太可能。在大多数情况下,您不应该在全球范围内定义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(); } } }
  4. 修改

    阅读您现在发布的完整代码块,我建议您进行一些更改。你可以运行以下内容并告诉我们它是否运行:

    <ngx-datatable class="material"
    [rows]="rows"
    [columnMode]="'force'"
    [headerHeight]="40"
    [footerHeight]="40"
    [rowHeight]="30"
    [externalPaging]="true"
    [limit]="50"
    [selectionType]="'checkbox'">
    <ngx-datatable-column
            [width]="30"
            [sortable]="false"
            [canAutoResize]="false"
            [draggable]="false"
            [resizeable]="false"
            [headerCheckboxable]="true"
            [checkboxable]="true">
          </ngx-datatable-column>
              <ngx-datatable-column name="Name">
                <ng-template let-value="value" ngx-datatable-cell-template>
                    <div class="redNumber">{{value}}</div>
                </ng-template>
          </ngx-datatable-column>
          <ngx-datatable-column name="Title"></ngx-datatable-column>
          <ngx-datatable-column name="company"></ngx-datatable-column>
          <ngx-datatable-column name="Status" [cellClass]="getStatusClass">  
      </ngx-datatable-column>
    <ngx-datatable-column name="Last connexion"></ngx-datatable-column>
    

    如果此版本运行正常,我们可以更好地挖掘问题。

答案 1 :(得分:1)

如果没有要迭代的数据,while循环将根本不执行。你需要检查HasRows吗?此外,在创建数据读取器时应使用CommandBehavior.CloseConnection。这将确保在您阅读完基础连接后关闭它。

Should if call SqlDataReader.HasRows if I am calling SqlReader.Read

SQLDataReader Source Code

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);
}