从多个语句中检索记录计数

时间:2015-01-16 21:28:47

标签: c# sql .net sql-server sqlclient

我编写了自己的SQL客户端,因为我厌倦了SSMS。我希望像SSMS一样捕获受影响的行计数,但SqlCommand.StatementCompleted完成时调用ExecuteReader 多次(或调用EndExecuteReader)。即使批处理中的语句以固定间隔完成,看起来DONE_IN_PROC消息在客户端上排队,然后一次性转储,而不是连续提升。没有InfoMessage个事件从SqlConnection开始执行。

斜体中的

更新

比如说,你有一个SQL语句来更新循环中的行,或类似的东西:

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

SSMS正确显示"(10行受影响)"每X秒或w / e。 没有来自阅读器的记录,因为这是仅UPDATE语句,因此无法使用SqlDataReader来计算行数。

是否可以使用SqlClient库?

有问题的简化代码是这样的:

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

发现类似的问题here,但描述不太清楚。

3 个答案:

答案 0 :(得分:0)

为什么不将sql移动到存储过程中。 使用带有包含输出参数的参数集合的命令对象来执行存储过程。在存储过程中有一个总计数变量,用于对受影响的每个更新行求和。将此作为输出参数返回。

答案 1 :(得分:0)

使用ExecuteNonQuery方法更新数据库时,它会返回受影响的行数。使用insert,update或delete sql命令时使用此方法。希望这是你正在寻找的。

答案 2 :(得分:0)

您要处理两个事件。 SqlConnection InfoMessageSqlCommand StatementCompleted

很抱歉VB代码,但你应该能够转换它。

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