Как узнать, что OracleCommand уже находится в состоянии Prepared?
Имею WinForm приложение и БД Oracle, к которой нужно корректно подключиться.
"Корректно" это вот так: если в момент выдачи очередного запроса кто-то выдернет сетевой шнур сервера из розетки, программа у клиента не виснет, а начинает тестировать связь с сервером (в цикле ping, затем tnsping, затем select * from dual) и после того как сервер снова оживёт, автоматически обратно коннектится и продолжает работу. Для этих целей написан код внизу, который выполняется в начале каждого обращения к БД из модулей программы.
private static Oracle.ManagedDataAccess.Client.OracleConnection oconn;
private static Oracle.ManagedDataAccess.Client.OracleCommand ocmd;
...
do try {
if (oconn.State == ConnectionState.Closed) oconn.Open();
if ((SQL.Length > 0) && (ocmd.CommandText != SQL)) ocmd.CommandText = SQL;
// вставить проверку: Prepared?,
// повторно Prepare() не выдавать, чтобы не валить сервер разборами запросов.
ocmd.Prepare();
} catch (Exception e) {
if (!uConnectTest.ConnectTest(null, e.Message)) { // модальный вызов модуля тестирования
Cursor.Current = Cursors.Default;
return false;
};
} while (oconn.State != ConnectionState.Open); // ??? вставить проверку успешности Prepare()
Дополнительно: хотелось бы держать часто выполняемый запрос в ocmd.CommandText открытым (в состоянии Prepared) в течении сессии, чтобы не валить сервер запросами, требующими разбора.
В цикле в блоке try/catch выполняются oconn.Open(), затем ocmd.Prepare().
Выход из цикла должен состояться только при условии успешности обоих команд.
Я знаю, как проверить успешность только первой из них: oconn.State != ConnectionState.Open
Вопрос:
Как проверить, что OracleCommand уже находится в состоянии Prepared для принятия решения, что повторно выдавать запрос на сервер не нужно и можно уже присваивать параметры/выполнять запрос? Метод Prepare() у него есть, а вот свойства Prepared не нашёл. Плохо искал?
Буду признателен за рекомендации или тычок куда смотреть...
Ответы (1 шт):
Комментариев много, а ответа нет. Попробую я его дать.
Нужно рассмотреть две стороны: серверную и клиентскую.
На сервере (СУБД) все запросы парсятся, составляется план и он кэшируется. Далее этот план используется и повторно время не тратится на парсинг sql и его составление. Причём не важно, откуда пришёл этот запрос: например, из приложения на Java или на Python - если он уже есть в кэше, то будет взят оттуда.
Когда-то раньше, в прошлые десятилетия, это было не так. Планы хранимых процедур хранились, а обычных запросов - нет. Вот тогда имели смысл prepared - подготовленные запросы. Можно было явно указать СУБД сохранять план в кэше. С тех пор памяти стало немеряно, движки СУБД изменились, нужда в явном указании исчезла.
Теперь клиентская сторона.
Наличие методов/функций/процедур наподобие prepare раньше было оправдано. Теперь, когда все запросы кэшируются, это стало рудиментом. Если посмотреть по ссылкам: 1, 2 - об этом прямо говорится в документации. Метод есть, но он ничего не делает.
В некоторых языках/фреймворках до сих пор есть такое понятие как prepared statement или prepared query. В других вместо этого существует термин parameterized query. В обоих случаях, это параметризованный запрос.
Суть в том, что параметризованный запрос, хранящийся в СУБД, можно многократно выполнять с разными значениями параметров. При этом он не парсится повторно. То есть он подготовлен (prepared) один раз и на этом всё.
Теперь собственно ответ на ваш вопрос.
Проверять явно в коде ничего не нужно. При восстановления соединения после обрыва, при выполнении запроса его план будет взят из кэша, если он там есть.