我编写了自己的SQL客户端,因为我厌倦了SSMS。我想像 SSMS 一样捕获受影响的行计数,但SqlCommand.StatementCompleted
在完成(或调用EndExecuteReader
)时会多次引发ExecuteReader
。即使批处理中的语句以固定的间隔完成,似乎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 每 X 秒数或 w/e 正确显示"(受影响的 10 行)"。没有来自读取器的记录,因为这是仅 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
}));
}
}
}
}
}
}
这里有一个类似的问题,尽管描述不太清楚。
有两个事件需要处理。SqlConnection
InfoMessage
和SqlCommand
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
为什么不将 sql 移动到存储过程中。使用具有包含输出参数的参数集合的命令对象执行存储过程。在存储过程中,有一个 total count 变量,用于对受影响的每个更新行求和。将其作为输出参数返回。
使用 ExecuteNonQuery 方法更新数据库时,它会返回受影响的行数。使用插入、更新或删除 sql 命令时,将使用此方法。希望这就是你要找的。