gendalf |
Отправлено: 06.12.2005, 13:06 |
|
Не зарегистрирован
|
БД Oracle
На форме TQuery, TDatabase, TDataSource, TDBGrid.
select-м забираю данные, состоящие из нескольких строчных полей и одного поля типа Blob. Далее нужно анализировать строчные поля и, при необходимости, сохранять Blob в файл. Вот тут и не получается.
Код примерно такой:
Q1->Next();
if (Q1->Fields->Fields[x]->AsString == "..." && Q1->Fields->Fields[x1]->IsBlob()) {
// сохранить blob в файл
}
В if пытался использовать TMemoryStream, TBlobStream, TBlobField, TBlobByteData — или ошибки в runtime, или пусто (для TBlobByteData).
Перерыл Examples в Buildere — ничего.
Сам на Buildere пишу не первый год, вроде, но с базами раньше дела не имел совсем. Неделю бьюсь уже, помогите, пож-та. |
|
AVC |
Отправлено: 06.12.2005, 13:46 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
TBlobField->SaveToFile() должно работать
Вот рабочий код (правда связка не BDE а DOA)
CODE |
//---------------------------------------------------------------------------
// From Table to Disk
//---------------------------------------------------------------------------
void __fastcall TForm1::Bt_ToDiskClick(TObject *Sender)
{
TOracleDataSet *qry = QryMain;
AnsiString str;
if (!qry || !qry->Active || qry->IsEmpty()) return;
TField *fldfname = qry->FindField("FileName");
if (!fldfname) return;
if (!qry->FindField("Content")) return;
TBlobField *fldcontent = dynamic_cast<TBlobField*>(qry->FieldByName("Content"));
if (!fldcontent) return;
str = AnsiString("") +
"Содержимое всех записей будет сохранено в каталоге <" + FLocalDir + ">" +
"\n\nВыполнить ?"
;
if (Application->MessageBox(str.c_str(), "", MB_YESNO) != IDYES) return;
AnsiString fname;
for (qry->First(); !qry->Eof; qry->Next())
{ fname = FLocalDir + fldfname->AsString;
if (FileExists(fname))
{ try { DeleteFile(fname); }
catch (...) {; }
}
try { fldcontent->SaveToFile(fname); }
catch (...)
{ ShowMessage("Ошибка при создании файла <" + fname + ">\n");
}
} // !qry->Eof
}
| |
|
gendalf |
Отправлено: 06.12.2005, 14:31 |
|
Не зарегистрирован
|
Компилятор на TOracleDataSet выдал "Undefined symbol", в Include объявление такого класса нет: или из-за того, что у меня Builder 5, или при при установке что-то не выбрал. Поменял на TDataSet — в runtime ошибка на строку:
fldcontent->SaveToFile(fname);
"Invalid BLOB handle in record buffer"
|
|
avc* |
Отправлено: 06.12.2005, 14:52 |
|
Не зарегистрирован
|
> TOracleDataSet выдал
Это закономерно, я ведь написал — код для DOA.
>"Invalid BLOB handle in record buffer"
Странно, сейчас попробую набросать для BDE. |
|
AVC |
Отправлено: 06.12.2005, 15:35 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Попробовал.
Все получилось с первого раза.
Форма, на форме Session, Database, Query, DataSet, сетка (просто для глаз). Все связано. Кнопка с уже приведенным кодом.
Жму. Из каталога приложения забираю файлы.
Для справки: в таблице хранятся файлы в формате MSWord (doc), поле имеет тип BLOB.
На всякий случай цепляю действующий (у меня) пример.
|
|
gendalf |
Отправлено: 07.12.2005, 10:36 |
|
Не зарегистрирован
|
Спасибо, посмотрел Ваш пример, но не помогло. Я попробовал изменить пример под мои нужды. Я изменил:
- SQL в Query1
- в Database: Params, DriverName — "Oracle" (при AliasName "HHCDev (Oracle BDE)" была ошибка "неизвестный алиас" + его нет в списке во время дизайна)
Да, база не на моей машине находится, сразу нужно было сказать наверное.
Вопросы:
- AliasName "HHCDev (Oracle BDE)" у меня нет, коннект к базе с таким алиасом не получается. Может в этом проблема?
- не ясна роль TSession в примере. В свой проект добавил, изменений нет.
- как можно узнать, действительно ли приложение получило blob поле, я пробовал смотреть fldcontent->Size, он равен 1 — это неправильно, по моему. |
|
avc* |
Отправлено: 07.12.2005, 11:42 |
|
Не зарегистрирован
|
> AliasName "HHCDev (Oracle BDE)" у меня нет, коннект к базе с таким алиасом не получается.
И не получится, это же моя база.
Alias и все прочее с ним конечно же у вас не такие как у меня. Предпологалось что связь с базой у вас настроена. Если это не так то попробуйте в SQLExplorer'е создать алиас (я использовал BDE'ешный драйвер для Oracle) и поработать со своей таблицей.
> не ясна роль TSession
TSession удобен для централизации связи с сервером (BDE все равно его использует, так пусть это будет явно).
> Да, база не на моей машине находится, сразу нужно было сказать наверное.
Это и не требется. У меня, конечно, тоже и даже под управлением другой ОС. Я воспользовался первой встреченой таблицей с полем BLOB на сервере разработки.
А вот Oracle у нас стоит 8i, хотя думаю что это не должно играть особой роли.
> как можно узнать, действительно ли приложение получило blob поле
Я для этого использую иногда dynamic_cast а иногда анализ Field->DataType, по обстановке.
Можете сообщить скрипт таблицы и примерные данные для Blob, буде время — попробую смоделировать.
PS. Если вы пишете приложениедля Oracle переходите на DOA или ODAC |
|
gendalf |
Отправлено: 07.12.2005, 12:00 |
|
Не зарегистрирован
|
> Предпологалось что связь с базой у вас настроена.
Настоена. Из SQLNavigator-а все получается — и достать blob и сохранить. Если бы не бинарные данные и писать ничего не пришлось бы, хватало и sqlplus-а + скрипты.
> Я для этого использую иногда dynamic_cast а иногда анализ Field->DataType, по обстановке.
Я не про это. Имел в виду следующее: параллельно делал такие же select-ы ручками и смотрел содержимое blob, размер был явно не 1
> PS. Если вы пишете приложениедля Oracle переходите на DOA или ODAC
Спасибо, попробую.
И еще, что же все-таки имеется в виду "Invalid BLOB handle in record buffer"? |
|
|