我编写了自己的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,但描述不太清楚。
答案 0 :(得分:0)
为什么不将sql移动到存储过程中。 使用带有包含输出参数的参数集合的命令对象来执行存储过程。在存储过程中有一个总计数变量,用于对受影响的每个更新行求和。将此作为输出参数返回。
答案 1 :(得分:0)
使用ExecuteNonQuery方法更新数据库时,它会返回受影响的行数。使用insert,update或delete sql命令时使用此方法。希望这是你正在寻找的。 p>
答案 2 :(得分:0)
您要处理两个事件。 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