У меня есть проблема при работе с простым методом вставки, время от времени зависающее из-за запланированной задачи очистки в таблице базы данных. Эта задача выполняется каждые десять минут, и во время ее выполнения мой код часто записывает ошибку в журнале событий из-за "ожидания ожидания".
Одно из решений, которое я рассматриваю, - сделать код, вызывающий хранимую процедуру асинхронным, и для этого я сначала начал искать метод BeginExecuteNonQuery.
Я попытался использовать метод BeginExecuteNonQuery, но обнаружил, что он довольно часто не вставляет строку вообще. Код, который я использовал, выглядит следующим образом:
SqlConnection conn = daService.CreateSqlConnection(dataSupport.DBConnString);
SqlCommand command = daService.CreateSqlCommand("StoredProc");
try {
command.Connection = conn;
command.Parameters.AddWithValue("page", page);
command.Parameters.AddWithValue("Customer", customerId);
conn.Open();
command.BeginExecuteNonQuery(delegate(IAsyncResult ar) {
SqlCommand c = (SqlCommand)ar.AsyncState;
c.EndExecuteNonQuery(ar);
c.Connection.Close();
}, command);
} catch (Exception ex) {
LogService.WriteExceptionEntry(ex, EventLogEntryType.Error);
} finally {
command.Connection.Close();
command.Dispose();
conn.Dispose();
}
Очевидно, что я не ожидаю мгновенной вставки, но я ожидаю, что она будет вставлена через пять минут в базу данных разработки с низким уровнем использования.
Теперь я переключился на следующий код, который делает вставку:
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
using (SqlConnection conn = daService.CreateSqlConnection( dataSupport.DBConnString)) {
using (SqlCommand command = daService.CreateSqlCommand("StoredProcedure")) {
command.Connection = conn;
command.Parameters.AddWithValue("page", page);
command.Parameters.AddWithValue("customer", customerId);
conn.Open();
command.ExecuteNonQuery();
}
}
});
У меня есть несколько вопросов, некоторые из них - предположения:
Поскольку моя подпись метода вставки недействительна, я предполагаю, что код, вызывающий ее, не ждет ответа. Это верно?
Есть ли причина, по которой BeginExecuteNonQuery не запускает хранимую процедуру? Является ли мой код неправильным?
Самое главное, если я использую QueueUserWorkItem (или хорошо выполненный BeginExecuteNonQuery), я прав, думая, что это будет иметь желаемый результат? Что означает, что попытка запуска хранимой процедуры во время выполнения запланированной задачи увидит, что код выполняется после завершения задачи, а не из-за ее текущего времени?
редактировать
Это версия, которую я использую сейчас в ответ на полученные комментарии и ответы.
SqlConnection conn = daService.CreateSqlConnection(
string.Concat("Asynchronous Processing=True;",
dataSupport.DBConnString));
SqlCommand command = daService.CreateSqlCommand("StoredProc");
command.Connection = conn;
command.Parameters.AddWithValue("page", page);
command.Parameters.AddWithValue("customer", customerId);
conn.Open();
command.BeginExecuteNonQuery(delegate(IAsyncResult ar) {
SqlCommand c = (SqlCommand)ar.AsyncState;
try {
c.EndExecuteNonQuery(ar);
} catch (Exception ex) {
LogService.WriteExceptionEntry(ex, EventLogEntryType.Error);
} finally {
c.Connection.Close();
c.Dispose();
conn.Dispose();
}
}, command);
Есть ли причина, по которой BeginExecuteNonQuery не запускает хранимую процедуру? Является ли мой код неправильным?
Возможно, вы не добавили в строку подключения Asynchronous Processing=True
.
Также - может быть ситуация, когда ответ от sql готов - ответ asp.net уже отправлен.
что вам нужно использовать: PageRegisterASyncTask (+AsyncTimeout)
(если вы используете асинхронные страницы webform, вы должны добавить в директиву страницы: Async="True"
)
ps эта строка в:
System.Threading.ThreadPool.QueueUserWorkItem
является опасным в приложениях asp.net. вы должны позаботиться о том, чтобы ответ еще не был отправлен.