2015-01-16 2 views
0

Я написал свой собственный 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 строк пострадавших)» каждый Х количество секунд, или ж/д. Нет записей, поступающих от читателя, так как это оператор только для UPDATE, поэтому для подсчета строк использовать .

Возможно ли, используя библиотеку 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

Какой код вы используете для выполнения инструкции SQL? – theMayer

+0

@ theMayer bread & butter SqlClient: SqlConnection, SqlCommand, ExecuteReader. –

+0

Это умело, но я хотел бы увидеть полную реализацию того, что вы делаете. – theMayer

ответ

0

Есть два события, которые вы хотите обработать. SqlConnectionInfoMessage и SqlCommandStatementCompleted.

Извините за код 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 
+0

См. Обновленный вопрос. 'StatementCompleted' действительно поднимается для каждого утверждения, но только когда заканчивается' ExecuteReader'. В принципе, я получаю множество событий «StatementCompleted» сразу. Между тем, партия выполняет, и я не знаю, работает ли она успешно или нет - пока это не будет сделано. –

+0

@ mr-ta Мой код из приложения asp.net, где все записывается в один поток, и он создает сообщения в правильном порядке. Я подозреваю, что вам может понадобиться использовать async/wait, но я не знаком с этим. – Nicholas

+0

@ mr-ta Еще одна вещь, вы используете печать или raiserror в своем sql-коде? Я думаю, что печать задерживается до тех пор, пока не будет возвращен результат или партия. Попробуйте использовать raiserror ('msg', 0, 0); в вашем sql-коде и посмотреть, что произойдет. – Nicholas

0

Почему вы не перемещаете sql в хранимую процедуру. Выполнение хранимой процедуры с использованием объекта команды с набором параметров, включающим выходной параметр. Внутри хранимой процедуры есть общая переменная счетчика для суммирования каждой из затронутых отдельных строк обновления. Вернуть это как выходной параметр.

+0

Ваше предложение отклоняет требование, которое я пытаюсь удовлетворить. Я пытаюсь заставить SQL-клиент, который я написал, работает немного как SSMS: сообщайте об оцененных количествах строк, как выполняется команда с несколькими операторами. Я, очевидно, могу сделать что-то подобное, настроив SQL, но это побеждает точку с SQL-клиентом: он должен делать что-то подобное сам по себе. –

0

Когда вы обновляете db с помощью метода ExecuteNonQuery, он возвращает количество затронутых строк. Этот метод используется, когда вы используете команду вставки, обновления или удаления sql. Надеюсь, это то, что вы ищете.

+0

Это не сработает. Этот метод возвращает только один счетчик записей. Мне нужно записать 0 или более счетчиков из нескольких операторов в пакете. Перечитайте мой вопрос, один из самых частых сценариев - очень длинная работа, разбитая на петлю. Невозможно разбить пакет SQL, содержащий цикл, на несколько вызовов ExecuteNonQuery. –

+0

Вы пробовали ответ, указанный в [этой ссылке] (http://stackoverflow.com/questions/1880471/capture-stored-procedure-print-output-in-net)? – Bhaskar

+0

См. Обновленный вопрос. –

Смежные вопросы