powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
14 сообщений из 14, страница 1 из 1
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33278521
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос.
Мы в приложении на С++ обращаемся к Oracle через OLE DB.

Используется один и тот же ICommandText, в который по мере надобности сажается новый запрос. Так вот иногда при n-ном вызове ICommandText::SetCommandText возвращает DB_E_OBJECTOPEN. Вроде как Rowset открыт.

При этом после скачивания данных всегда вызываются:
hr = pIRowset->ReleaseRows( cRowsObtained,&rghRow, NULL, NULL, NULL );
hr = pIRowset->Release();
// output accessor
hr = pIAccessor->ReleaseAccessor(hOutputAccessor,NULL);
hr = pIAccessor->Release();
Чего ж им ещё нехватает?

Сажать каждый раз пустой текст в ICommandText::SetCommandText помогло бы (ICommandText вернулся бы при этом в изначальное состояние), но мы этого делать не можем, потому что команду в некоторых случаях используют многократно.

Есть ли какой-нибудь другой способ "закрыть" Rowset, не убив при этом команду?
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33278661
Станислав C.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lana K.
Сажать каждый раз пустой текст в ICommandText::SetCommandText помогло бы (ICommandText вернулся бы при этом в изначальное состояние), но мы этого делать не можем, потому что команду в некоторых случаях используют многократно.

Есть ли какой-нибудь другой способ "закрыть" Rowset, не убив при этом команду?
А что, нельзя команды для сохранения помещать, например, в CStringList? А при необходимости их "выковыривать" оттуда? А в ICommandText все-таки помещать пустую строку для его возвращения в первоначальное состояние...
Это будет типа "истории команд" (как было в Norton Commander'е, FAR'e по набору Alt+F8) и пользователь сможет вызвать на исполнению любую из ранее набранных комманд...
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33278990
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сажать пустую команду - это именно то, чего мне хотелось бы избежать. Приложение очень большое, состоит из нескольких программ (модулей). Недавно я столкнулась с тем, что в нескольких местах исходят из того, что команды "не обнуляются". Эти места я могла бы переделать, хотя очень не хочется :-(, но нет гарантии, что я все такие места отловлю. Поэтому я и ищу другой способ.
Кроме того есть ещё один аргумент против такого решения: если сажать пустую строку, то команда, которая до этого уже была "подготовлена" у Oracle, должна будет при следующем вызове опять по новой готовиться. Тоже вроде как не очень красиво.

Должен же существовать ещё какой-нибудь способ "закрыть" Rowset?
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33279040
Станислав C.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lana K.Должен же существовать ещё какой-нибудь способ "закрыть" Rowset?
Ну, можно, например, пересоздать объект pIRowset: Старый удалить по pIRowset.Release(), а затем снова сделать CreateInstance(....)...
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33279151
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм, ... и потом опять удалить? Спасибо, я попробую.
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33279682
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну а в документации слабо посмотреть, да? Специальная глава для вас написана.
OLE DB Programmer's Reference

Releasing Rowsets
When the consumer is done with the rowset, it must release it as follows:

If the consumer has created any accessors on the rowset, it must release them by calling IAccessor::ReleaseAccessor on each accessor individually.
To release the rowset object itself, the consumer must call IUnknown::Release on each interface pointer retrieved on the rowset. When the rowset is released, it forces the release of any remaining row handles the consumer holds. Such handle objects are subordinate to the rowset and cannot cause it to linger beyond the point where all the interfaces for the rowset have been released. The rowset is responsible for cleaning up all such subordinate objects.
Note If the consumer obtained the rowset by executing a command containing output parameters and the provider populates output parameters when the rowset is released (that is, the value of DBPROP_OUTPUTPARAMETERAVAILABILITY is DBPROP_OA_ATROWRELEASE), the consumer must ensure that memory allocated for the output parameters that were bound at ICommand::Execute time must still be valid when the rowset is released. Not doing so is a serious programming error that can cause abnormal termination.
This topic is a part of:

Chapter 4: Rowsets
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33283969
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Станислав C.

К сожалению не получилось. Если команда уже посажена, то просто так от балды Rowset создать не получится. Т. е. и Accessor-ы соответствовать команде должны и тд. и тп. В результате та же петрушка.

Есть ли хотя бы какая-нибудь возможность узнать, что там именно висеть остаётся? Например до Release-ания Rowset-а проверить, жив ли ещё какой- нибудь его Accessor? (А в идеале- ещё и какой именно?)


2 White Owl

Спасибо большооое за информацию. Не поверите: уже читала. А вот вы вопрос читали? Проблема именно в том, что вроде как на первый взгляд всё корректно удаляется. И на второй взгляд, и на десятый тоже. Что-то всё-таки остаётся - судя по DB_E_OBJECTOPEN в какой-то момент. Что именно остаётся - пока словить не получилось. Мои предшественники судя по комментариям в кодах с этой проблемой сталкивались и вышли из положения просто: сажали каждый раз пустой текст в ICommandText::SetCommandText. Это переводит команду в изначальное состояние и снимает все проблемы. По причинам, которые я описала выше, мне приходится сейчас это переделывать. Так что если у вас по теме идеи будут, то буду очень благодарна.
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33284508
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Некрасиво, но работает:

Код: plaintext
1.
2.
3.
4.
5.
6.
HRESULT	hr =  0 ;
ICommandPrepare*	pICommandPrepare = NULL;
if(SUCCEEDED(hr = m_ICommandText->QueryInterface(IID_ICommandPrepare, (void**)&pICommandPrepare)))
  {
    hr = pICommandPrepare->Unprepare();
    pICommandPrepare->Release();
  }

Мою проблему это решает: команда не обнуляется, но и ошибка "DB_E_OBJECTOPEN" больше не вылезает. Конечно Prepare каждый раз по-новой делать надо, что не есть гуд.

Что интересно: ICommandPrepare::Unprepare() тоже DB_E_OBJECTOPEN должна бы вернуть если Rowset открыт, но этого не делает. Молчит как рыба об лёд, в смысле S_OK возвращает. А если Unprepare не вызываю, то DB_E_OBJECTOPEN рано или поздно при ICommandText::SetCommandText вылезает.

Хм. Не ндравится мне это...
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33284634
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lana K.Спасибо большооое за информацию. Не поверите: уже читала.
Читала, да недостаточно внимательно :)
When the rowset is released, it forces the release of any remaining row handles the consumer holds. Such handle objects are subordinate to the rowset and cannot cause it to linger beyond the point where all the interfaces for the rowset have been released. The rowset is responsible for cleaning up all such subordinate objects.
То есть сначала освобождаем plAccessor, а потом plRowSet.
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33284668
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 White Owl

Упс, претензии по-поводу непрочитанного вопроса снимаются, звиняйте. :-)
Теперь поняла, к чему была цитата.
Но по теме: это я в вопрос неаккуратно вставила, случайно в неправильном порядке. На самом деле сперва освобождаются Accessor-ы (все что есть, например и параметровые, и строковые и т.д.). И сами строки освобождаются совсем в другом месте, по мере загрузки. А вот IRowset::Release уже после всего этого вызывается.

Так что проблема не в этом.
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33286816
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lana K.И сами строки освобождаются совсем в другом месте, по мере загрузки. А вот IRowset::Release уже после всего этого вызывается.
Если у вас такое размазаное по коду освобождение ресурсов, то это очень не хорошо. Скорее всего, где-то происходит исключение и управление просто перепрыгивает через команды освобождения внутренних структур. Это кстати объясняет и почему ошибка появляется не всегда. Я бы, в первую очередь сейчас, облазил тот кусок кода который по идее должен бы освобождать внутренние ресурсы. И поискал бы там команду которая может выдвать исключение не отлавливаемого типа.
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33286892
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlЕсли у вас такое размазаное по коду освобождение ресурсов, то это очень не хорошо.
Эт точно. Только у нас ещё много чего нехорошего, всего не переделаешь :-(.

Но я нашла ситуацию, в которой эта ошибка воспроизводится стопроцентно. В отладчике всё многократно проиграла: все места с освобождением чего-либо вызываются, причем в нужном порядке, и возвращается всегда полный ОК.
И не смотря на это потом DB_E_OBJECTOPEN вылезает. Я всё-таки подозреваю, что енто глюк, а разбираться с этим по-серьёзному времени у меня мало. Я и так за последние пару месяцев 2 баги по OLE DB на оракле открыть заставила, и каждый раз с бизнес кейсом, тестовыми оболочками и километровыми переговорами с саппортом. Надоели.

Почему я думаю, что это глюк.
1. Вроде с виду всё правильно выполняется.
2. Когда я встроила вызов pICommandPrepare->Unprepare, он по идее должен был бы в том же самом месте тоже DB_E_OBJECTOPEN вернуть, если бы не всё освобождалось бы, или? А отрабатывается всё с ОК.
3. Я уже когда-то сталкивалась с таким же явлением в маленькой тестовой программке, не имеющей к нашей махине никакого отношения. Программку эту я тогда для совсем другой цели делала, на эту проблему тоже времени терять не хотелось и я просто чтобы не возиться сбивала каждый раз команду на пустой текст (там это не мешало). К сожалению програмку найти сейчас не смогла. Потом вот столкнулась с тем, что не я одна такая хитрая. Но только вот в нашей махине это "обнуление" боком вылезало, пришлось переделывать.

Логично? (вопрос в основном про пункт 2)
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33286900
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lana K.2. Когда я встроила вызов pICommandPrepare->Unprepare, он по идее должен был бы в том же самом месте тоже DB_E_OBJECTOPEN вернуть, если бы не всё освобождалось бы, или? А отрабатывается всё с ОК.
...
Логично? (вопрос в основном про пункт 2)
Не совсем логично. ICommandPrepare::Unprepare не будет работать вообще если по каким-то причинам команда была запущена без предварительного ICommandPrepare::Prepare. То есть она может проверить флаг подготовленности - нет флага, сразу выходим не проверяя открыт резалт-сет или нет. Это поведение конечно будет различаться в разных драйверах, но....
...
Рейтинг: 0 / 0
Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
    #33289165
Lana K.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl Lana K.2. Когда я встроила вызов pICommandPrepare->Unprepare, он по идее должен был бы в том же самом месте тоже DB_E_OBJECTOPEN вернуть, если бы не всё освобождалось бы, или? А отрабатывается всё с ОК.
Не совсем логично. ICommandPrepare::Unprepare не будет работать вообще если по каким-то причинам команда была запущена без предварительного ICommandPrepare::Prepare. То есть она может проверить флаг подготовленности - нет флага, сразу выходим не проверяя открыт резалт-сет или нет. Это поведение конечно будет различаться в разных драйверах, но....

Могло бы быть и так. Но поведение программы врят ли бы так от вызова ICommandPrepare::Unprepare изменилось бы, если там ничего не происходило. А факт налицо: после вызова ICommandPrepare::Unprepare ошибка больше не вылезает.
Но я несмотря на эти соображения ещё раз всё облазила и внимательно в отладчике прокрутила. ICommandPrepare::Prepare вызывается. И отрабатывается всё без ошибок.
Так что если у вас есть другие идеи, сомнения и примечания, то всегда пожалуйста.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Oracle OLE DB, DB_E_OBJECTOPEN, как закрыть Rowset?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]