|
ADODB асинхронное выполнение BACKUP DATABASE и получение прогресса | ☑ | ||
---|---|---|---|---|
0
TormozIT
гуру
23.08.15
✎
21:48
|
Решаю задачу выполнения резервного копирования базы в MSSQL с отображением прогресса в форме (асинхронно). Решаю долго и мучительно. Пока не успешно. Ниже код через ADODB
ADODBCommand.CommandText = "BACKUP DATABASE TO DISK='my.bak' WITH STATS=10"; Options = adAsyncExecute + adExecuteNoRecords"; // 16 + 128 ADODBCommand.Execute(RecordsAffected, Null, Options); Пока ADODBCommand.State = 4 Цикл ПаузаИис(1); Если ADODBCommand.ActiveConnection.Errors.Count > 0 Тогда Сообщить(ADODBCommand.ActiveConnection.Errors.Count); КонецЕсли; КонецЦикла; Асинхронно процесс выполняется, но прогресс в виде текстовых сообщений в свойстве Errors появляется только после завершения выполнения команды (когда ADODBCommand.State = 0). И даже тогда он появляется только в количестве 1 сообщение (первый вывод прогресса). На sql.ru уже порылся. http://www.sql.ru/forum/731198/tadocommand-v-asinhronnom-rezhime |
|||
1
TormozIT
гуру
23.08.15
✎
22:02
|
Если подключить обработчик события ADODB.Connection.InfoMessage, то он вызывается опять же только после завершения выполнения команды и ровно 3 раза всегда с одним и тем же сообщением прогресса.
|
|||
2
МихаилМ
23.08.15
✎
23:50
|
ms sql profiler вам поможет. либо наведет на правильную строку поиска
|
|||
3
DmitrO
24.08.15
✎
08:59
|
http://dev.citykirov.ru/
Обработка ВосстановлениеБД. Там это есть. Глянь. Написана давным давно, проблем с получением прогресса при бекапе вроде у меня не было. |
|||
4
vde69
24.08.15
✎
09:18
|
смотри в типовых
ДлительныеОперации.СообщитьПрогресс(Всего, мТекущийАдрес) |
|||
5
TormozIT
гуру
24.08.15
✎
09:34
|
(3) Касперский на этот сайт выругался. Можешь кинуть на почту или файлообменник?
|
|||
6
DmitrO
24.08.15
✎
09:41
|
(5)отправил по почте
|
|||
7
vde69
24.08.15
✎
09:45
|
// Регистрирует в сообщениях информацию о ходе выполнения фонового задания.
// В дальнейшем эту информацию можно считать с клиента при помощи функции ПрочитатьПрогресс. // // Параметры: // Процент - Число - Необязательный. Процент выполнения. // Текст - Строка - Необязательный. Информация о текущей операции. // ДополнительныеПараметры - Произвольный - Необязательный. Любая дополнительная информация, // которую необходимо передать на клиент. Значение должно быть простым (сериализуемым в XML строку). // Процедура СообщитьПрогресс(Знач Процент = Неопределено, Знач Текст = Неопределено, Знач ДополнительныеПараметры = Неопределено) Экспорт ПередаваемоеЗначение = Новый Структура; Если Процент <> Неопределено Тогда ПередаваемоеЗначение.Вставить("Процент", Процент); КонецЕсли; Если Текст <> Неопределено Тогда ПередаваемоеЗначение.Вставить("Текст", Текст); КонецЕсли; Если ДополнительныеПараметры <> Неопределено Тогда ПередаваемоеЗначение.Вставить("ДополнительныеПараметры", ДополнительныеПараметры); КонецЕсли; ПередаваемыйТекст = ОбщегоНазначения.ЗначениеВСтрокуXML(ПередаваемоеЗначение); Сообщение = Новый СообщениеПользователю; Сообщение.Текст = ПередаваемыйТекст; Сообщение.Сообщить(); КонецПроцедуры // Находит фоновое задание и считывает из его сообщений информацию о ходе выполнения. // // Возвращаемое значение: // Структура - Информация о ходе выполнения фонового задания. // Ключи и значения структуры соответствуют именам и значениям параметров процедуры СообщитьПрогресс(). // Функция ПрочитатьПрогресс(Знач ИдентификаторЗадания) Экспорт Перем Результат; Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания); Если Задание = Неопределено Тогда Возврат Результат; КонецЕсли; МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина); Если МассивСообщений = Неопределено Тогда Возврат Результат; КонецЕсли; Количество = МассивСообщений.Количество(); Для Номер = 1 По Количество Цикл ОбратныйИндекс = Количество - Номер; Сообщение = МассивСообщений[ОбратныйИндекс]; Результат = ОбщегоНазначения.ЗначениеИзСтрокиXML(Сообщение.Текст); Прервать; КонецЦикла; Возврат Результат; КонецФункции |
|||
8
TormozIT
гуру
24.08.15
✎
09:58
|
(4) (7) Проблема не в регистрации/отображении, а в асинхронном получении информации о прогрессе от MSSQL через ADODB
|
|||
9
TormozIT
гуру
24.08.15
✎
10:54
|
(6) Спасибо. Оказалось, что проблема с получением сообщений о прогрессе по ходу выполнения команды была из-за CursorLocation, который в моем случае был 3 (клиент), а нужно было 2 (сервер).
|
|||
10
TormozIT
гуру
24.08.15
✎
10:57
|
Похоже при асинхронном вызове Execute() все таки получать прогресс нельзя. При синхронном работает такой способ
RS = Connection.Execute(ТекстЗапроса); Пока RS<>Неопределено Цикл Warning = Connection.Errors(0); Если Warning.NativeError=3211 Тогда ТекстСообщения = Warning.Description; ИндикаторВыполнения = Число(Лев(ТекстСообщения, Найти(ТекстСообщения, " ")-1)); КонецЕсли; RS = RS.NextRecordset(); КонецЦикла; |
|||
11
mistеr
24.08.15
✎
11:00
|
Сомневаюсь, что можно дбиться желаемого через ADODB.
|
|||
12
DmitrO
24.08.15
✎
11:01
|
(10)при асинхронном надо через события работать
|
|||
13
TormozIT
гуру
24.08.15
✎
11:02
|
(12) Пробовал. Не помогает (1)
|
|||
14
DmitrO
24.08.15
✎
11:12
|
(13)а если ExecuteComplete обрабатывать, а не InfoMessage?
|
|||
15
TormozIT
гуру
24.08.15
✎
12:22
|
(14) Судя по описанию, должно получиться. Но пока сделал синхронно и с частыми обновлениями работает приемлемо.
|
|||
16
Fram
24.08.15
✎
12:29
|
(10) а при таком способе проц не грузит на 100%?
|
|||
17
TormozIT
гуру
24.08.15
✎
13:21
|
(16) Вызов NextRecordset ждет получения очередного результата (сообщения о прогрессе). Процессор он не грузит, т.к. это синхронный внешний вызов. Поэтому их будет столько, сколько сообщений с прогрессом выдаст сервер.
|
|||
18
TormozIT
гуру
24.08.15
✎
15:50
|
При расположении курсора на сервере выполнение Rd1.NextRecordSet закрывает Rd1. А мне нужно чтобы он оставался открытым. При расположении курсора на клиенте ADODB.COMMAND.Execute() сначала ждет получения всех recordset'ов и только потом возвращает управление.
|
|||
19
Гёдза
24.08.15
✎
15:51
|
(18) покажи конечный код
|
|||
20
TormozIT
гуру
24.08.15
✎
15:57
|
РезультатЗапроса = ОбъектЗапрос.Execute(); // Тут ждет последнего результата при CursorLocation = 3
лРезультат = РезультатЗапроса; Пока лРезультат <> Неопределено Цикл РезультатЗапроса = лРезультат; Если СоединениеADO.Errors.Count > 0 Тогда Сообщение = СоединениеADO.Errors(0); Если Сообщение.NativeError = 3211 Тогда Сообщить(Сообщение.Description); КонецЕсли; КонецЕсли; лРезультат = РезультатЗапроса.NextRecordset(); // После выполнения этой строки при CursorLocation = 2 (сервер) объект в РезультатЗапроса закрывается КонецЦикла; КоличествоСтрок = РезультатЗапроса.RecordCount; // Тут ошибка при CursorLocation = 2 |
|||
21
DmitrO
24.08.15
✎
16:21
|
>>А мне нужно чтобы он оставался открытым.
>>КоличествоСтрок = РезультатЗапроса.RecordCount Мы восстанавливаем/бекапим базу, количество каких строк (чорт побери) хочется узнать при этом? :) RecordCount - это свойство доступно только при DML запросах (количество обработанных строк). Клиентский курсор имеет смысл только для DSL запросах (select), и по сути при помощи библиотеки курсоров загружает в память все что вернул сервер и позволяет потом бегать туда сюда по выборке. Что на самом деле малоэффективная и малоприменимая штука (щас это уже никому не надо, ни кто не применяет). |
|||
22
DmitrO
24.08.15
✎
16:24
|
DML это insert,update,delete
|
|||
23
TormozIT
гуру
24.08.15
✎
16:26
|
(21) У меня универсальная функция. Поэтому мне нужно обеспечить ее работу в большом числе ситуаций. Снижение ее универсальности повлечет обширные изменения.
|
|||
24
TormozIT
гуру
24.08.15
✎
16:35
|
В общем добавил в свою функцию параметр отвечающий за обновление прогресса вместе с выполнением NextRecordset, а получение последнего RecordSet для D*L запросов придется теперь делать снаружи этой функции.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |