Retrieve record counts from multiple statements

試著忘記壹切 提交于 2019-12-25 04:07:24

问题


I wrote my own SQL client because I was tired of SSMS. I want to capture the affected row counts just like SSMS but SqlCommand.StatementCompleted is raised multiple times when ExecuteReader finishes (or EndExecuteReader is called). Even though the statements in the batch complete with a regular interval, it seems like the DONE_IN_PROC messages are queued up on the client, and then dumped all at once, instead of being raised continuously. No InfoMessage events through-out the execution from SqlConnection, either.

Update above in italics.

Say, you have a SQL statement that updates rows in a loop, or something like that:

WHILE 1=1 
BEGIN 
  UPDATE tbl SET .... WHERE Id BETWEEN i AND i+10; 
  IF @@ROWCOUNT =0 BREAK; 
  SET i = i + 10; 
END

SSMS properly shows "(10 rows affected)" every X number of seconds or w/e. There are no records coming from the reader, since this is a UPDATE only statement, so can't use SqlDataReader to count the rows.

Is that possible, using the SqlClient library?

The simplified code in question is like this:

class ExecuteWorker
{
  public void Start(string query)
  {
    this._query = query;
    this._thread.Start(this.Work);
  }

  void Work()
  {
    using(var conn = new SqlConnection(this._connStr))
    {
      conn.Open();
      using(var command = conn.CreateCommand())
      {
        command.CommandText = this._query;
        using(var reader = command.ExecuteReader())
        {
          while(reader.Read())
          {
            this._control.BeginInvoke(new Action(()=>{
              // update UI
            }));
          }
        }
      }
    }
  }
}

A similar question is found here, though the description is less clear.


回答1:


There are two events that you want to handle. The SqlConnection InfoMessage and the SqlCommand StatementCompleted.

Sorry for the VB code but you should be able to convert it.

Private Sub OnInfoMessage(sender As Object, args As SqlClient.SqlInfoMessageEventArgs)
    For Each sqlEvent As System.Data.SqlClient.SqlError In args.Errors
        Dim msg As String = String.Format("Msg {0}, Level {1}, State {2}, Line {3}{4}", sqlEvent.Number, sqlEvent.Class, sqlEvent.State, sqlEvent.LineNumber, Environment.NewLine)
        'Write msg to output
    Next
End Sub

Private Sub OnStatementCompleted(sender As Object, args As StatementCompletedEventArgs)
    Dim msg As String = String.Format("({0} row(s) affected)", args.RecordCount)
    'Write msg to output
End Sub

Public Sub Work()
    Using dbc As New SqlConnection(Me.ConnectionString),
          dbcmd As New SqlCommand()

        dbcmd.Connection = dbc
        dbcmd.CommandTimeout = Convert.ToInt32(timeout) ' you will want to set this otherwise it will timeout after 30 seconds
        'set other dbcmd properties

        AddHandler dbc.InfoMessage, New SqlInfoMessageEventHandler(AddressOf OnInfoMessage)
        AddHandler dbcmd.StatementCompleted, AddressOf OnStatementCompleted

        dbc.Open()

        'dbcmd.ExecuteNonQuery() or Using dataReader As SqlDataReader = dbcmd.ExecuteReader()

    End Using
End Sub



回答2:


Why dont you move the sql into a stored procedure. Execute the stored procedure using a command object with a parameters collection including an output parameter. Within the stored procedure have a total count variable to sum each of the individual update rows affected. Return this as an output parameter.




回答3:


When you update the db using ExecuteNonQuery method, it returns number of rows affected. This method is used when you use insert, update or delete sql command. Hope this is what you are looking for.



来源:https://stackoverflow.com/questions/27993049/retrieve-record-counts-from-multiple-statements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!