Когда должен запускаться SqlCommand.StatementCompleted? - PullRequest
2 голосов
/ 20 января 2011

Обновление Нужно ли что-то уточнить в моем вопросе?Я поражен, увидев, что за две недели я не получил ни оценки, ни комментария, ни ответа.


Я пытаюсь написать простое приложение winforms, которое выполняет инструкцию SQL SELECT асинхронно.Когда сервер sql начинает возвращать результаты, я хочу выполнить обработчик событий, связанный с событием StatementCompleted SqlCommand.

Форма содержит две кнопки, текстовое поле и метку.Когда нажата кнопка1, я создаю SqlCommand и подключаю обработчик событий, затем открываю SqlConnection и вызываю BeginExecuteReader для запуска асинхронной операции.Я установил метку, чтобы показать, что команда выполняется.

В обработчике событий я просто устанавливаю метку, чтобы показать, что команда выполнена.

Когда нажата кнопка 2, я меняю меткучтобы показать, что мы обрабатываем результаты.Затем я вызываю EndExecuteReader и присваиваю его возвращаемое значение новому SqlDataReader, который затем обрабатываю.

Я вижу, что обработчик событий не вызывается, когда команда готова.Вместо этого он вызывается, когда мой код заканчивает обработку считывателя, возвращенного EndExecuteReader.

Я что-то здесь упустил?Я неправильно истолковываю предполагаемое использование события?Я попытался найти пример StatementCompleted, но я мог найти только общие описания этого, без рабочего кода.Пример на странице SqlCommand.BeginExecuteReader в MSDN использует цикл и ожидает, пока свойство IAsyncResult.IsCompleted будет иметь значение true.Я ожидаю, что в то же время, когда это свойство становится истинным, происходит событие StatementCompleted.

public Form1() {
    InitializeComponent();
}

private IAsyncResult iAsyncResult;
private SqlCommand sqlCommand;

private void statementCompleted(object sender,
                                StatementCompletedEventArgs e) {
    label1.Text = "Statement completed";
}

private void button1_Click(object sender, EventArgs e) {
    var northWindConnection =
        new SqlConnection(
            "Data Source=.\\SqlExpress;Initial Catalog=Northwind;" +
            "Integrated Security=True;" +
            "asynchronous processing=true");
    sqlCommand = new SqlCommand("WAITFOR DELAY '00:00:05';" +
                                " SELECT * FROM [Order Details]",
                                northWindConnection);
    sqlCommand.StatementCompleted += statementCompleted;
    northWindConnection.Open();
    iAsyncResult = sqlCommand.BeginExecuteReader();
    label1.Text = "Executing";
}

private void button2_Click(object sender, EventArgs e) {
    label1.Text = "Not waiting anymore, reading";
    var results = new StringBuilder();
    var reader = sqlCommand.EndExecuteReader(iAsyncResult);
    while (reader.Read()) {
        for (int i = 0; i < reader.FieldCount; i++) {
            results.Append(reader[i].ToString() + "\t");
        }
        results.Append(Environment.NewLine);
    }
    reader.Close();
    sqlCommand.Connection.Close();
    textBox1.Text = results.ToString();
}

Ответы [ 2 ]

2 голосов
/ 27 декабря 2011

Последовательность событий такая:

  1. Вызов SqlCommand.BeginExecuteReader(callback, stateObject) отправляет T-SQL на SQL Server, и команда начинает выполняться.
  2. Когда данные впервые доступны , вызывается AsyncCallback, предоставленный BeginExecuteReader().
  3. Обратный вызов вызывает EndExecuteReader() для получения ссылки на объект SqlDataReader.
  4. Вы используете SqlDataReader, чтобы прочитать результаты запроса. Это может быть один ряд или миллионы строк. Запрос не завершен, пока не будут возвращены все запрошенные данные.
  5. Повторите для дополнительных наборов результатов, если таковые имеются.
  6. Вызвать событие StatementCompleted - но только если запрос / хранимая процедура не использовала SET NOCOUNT ON.

Другими словами, StatementCompleted вызывается, когда T-SQL полностью завершен, включая все связанные передачи данных.

1 голос
/ 26 апреля 2011

Добавление этого для любого, кто может столкнуться с этим вопросом, поскольку он был задан несколько месяцев назад без ответов.

Событие StatementCompleted бесполезно при применении шаблона асинхронного вызова против SqlCommand.Это происходит, но только во время вызова EndExecuteReader, который в основном слишком поздно.Если вы хотите реализовать шаблон асинхронных вызовов в целом, эта статья MSDN содержит отличное объяснение того, как это можно сделать.Пример кода в документации BeginExecuteReader показывает правильное использование SqlCommand в асинхронном режиме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...