Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие СУБД 2011.pdf
Скачиваний:
68
Добавлен:
10.06.2015
Размер:
2.75 Mб
Скачать

92

Поля BLOB

Класс TBlobField реализован для обеспечения работы с двоичными большими объектами (binary large object, BLOB) переменной длины. Поля этого типа и его производные представляют собой универсальное хранилище большого объёма разнотипной информации. Поля BLOB широко представлены практически во всех СУБД. Например: в таблицах Paradox к таковым относятся большие текстовые поля (Memo), поля форматированного тек-

ста (FormattedMemo), графическое поле (Graphic).

Если рассуждать о специализации BLOB полей, то стоит обратить внимание на свойство:

property BlobType: TBlobType;

где

type TBlobType = ftBlob..ftOraClob;

Тип данных TBlobType это всего-навсего подмножество TFieldType. Значения, которые может принимать это тип данных, вы можете просмотреть в справочной системе. Хотя свойство BlobType доступно как для чтения, так и для записи, но если возникла необходимость, поменять тип поля целесообразнее вызвать метод:

Почти все методы BLOB поля нацелены на решение вопросов чтения или записи данных. Для загрузки данных в поле предназначены два метода:

procedure LoadFromFile(const FileName: string); procedure LoadFromStream(Stream: TStream);

В первом случае требуется передать имя графического файла FileName. Реализация второго метода несколько сложнее, в нём работа осуществляется с областью памяти – пото-

ком Stream.

Для выгрузки данных из поля реализованы два симметричных метода с аналогичными параметрами:

procedure SaveToFile(const FileName: string); procedure SaveToStream(Stream: TStream);

Для копирования данных из другого BLOB-поля определена процедура.

procedure Assign(Source: TPersistent);

Здесь в качестве параметра передаётся источник данных – Source. В роли источника данных могут выступать: другие BLOB поля, набор строк TStrings, графические объекты, например TBitmap.

Факт изменения данных внутри поля можно проверить, просмотрев свойство:

property Modified: Boolean;

Значение True является признаком, что поле изменялось.

Разработаем небольшой пример, демонстрирующий работу с BLOB полем. Задача заключается в следующем: нам требуется научить приложение сохранять в таблице растровую картинку и имя файла, соответствующего этому изображению. Начнём с проектирования структуры таблицы. Для решения поставленной задачи нам достаточно определить три поля: первичный ключ PICTURE_KEY, поле PICTUREBLOB для хранения графики и текстовое поле для хранения имени файла PICTURENAME. Воспользуемся услугами СУБД Microsoft Access 2007 и создадим в ней файл БД с именем blobdemo.accdb. База данных будет содержать единственную таблицу PICTURETABLE (см. рис 19.9) с описанными выше характеристиками.

© 2011 г. Д.Л. Осипов

93

Рисунок 15.1. Структура таблицы для работы с полем BLOB

Приступаем к работе в Delphi. Создаём новый проект и размещаем на главной форме следующий перечень компонентов: таблица – ADOTable1, диалог доступа к файлам в стиле Vista – FileOpenDialog1, объект Image1 – для отображения рисунков, метку для отображения названия файла – StaticText1, и семь кнопок класса TSpeedButton. Первые четыре кнопки (см. внешний вид формы на рисунке 15.2) предназначены для перемещения по записям внутри таблицы. Назовём их следующим образом: btnFirst – для перемещения на самую первую запись, btnPrior – предыдущая запись, btnNext – следующая запись, btnLast – последняя запись. Кроме имён кнопок потребуется изменить значения их свойств tag. Для btnFirst – 0, btnPrior – 1, btnNaxt – 2, btnLast – 3. И осталось три кнопки, отвечающие непосредственно за редактирование данных в таблице: btnAppend – добавляет новую запись в конец набора, btnEdit – редактирует текущую запись и btnDelete – отвечает за удаление.

Рисунок 15.2. Внешний вид формы для работы с BLOB-полем

Сохраните проект в том же каталоге где и расположен файл blobdemo.accdb. Главную форму проекта по традиции назовём frmMain.dfm, соответствующий ей модуль –

main.pas, а весь проект – blobdemo.dpr.

Настройте строку соединения для компонента ADOTable1.

В секции частных объявлений опишем заголовки двух процедур SetData() и GetData(). Процедура SetData() предназначена для организации загрузки файла рисунка в BLOB поле. Для этого вызывается диалог открытия изображения. Если пользователь выберет файл и при этом таблица находится в режиме вставки (dsInsert) или редактирования (dsEdit) оба поля записи будут заполнены соответствующими данными.

procedure TfrmMain.SetData; begin

if (FileOpenDialog1.Execute) and

((ADOTable1.State=dsInsert) or (ADOTable1.State=dsEdit)) then begin

(ADOTable1.FieldByName('PICTUREBLOB') as TBlobField).LoadFromFile(FileOpenDialog1.FileName); ADOTable1.FieldByName('PICTURENAME').AsString:=

ExtractFileName(FileOpenDialog1.FileName);

© 2011 г. Д.Л. Осипов

94

end; end;

Процедура GetData() предназначена для извлечения данных из текстового и BLOB поля. Название файла загружается в Caption компонента StaticText1. Если поле Image не пусто, то мы создаём поток M:TMemoryStream, загружаем в него данные из поля, и передаём их в компонент Image1. Обращаю внимание, на то что, перед передачей данных из потока его следует установить на нулевую позицию. В заключении освобождаем ресурсы, занимаемые потоком, вызвав метод Free().

procedure TfrmMain.GetData; var M : TMemoryStream; begin

with ADOTable1 do begin

StaticText1.Caption:=FieldByName('PICTURENAME').AsString;

if (FieldByName('PICTUREBLOB') as TBlobField).IsNull=False then begin

M:=TMemoryStream.Create;

(FieldByName('PICTUREBLOB') as TBlobField).SaveToStream(M); M.Position:=0;

Image1.Picture.Bitmap.LoadFromStream(M);

M.Free;

end else Image1.Picture.Bitmap.FreeImage; end;

end;

После того, как были созданы ключевые процедуры чтения и записи данных, переходим к описанию основных событий. Первое из них – событие OnCreate() главной формы проекта. В нём мы осуществим подключение компонента ADOTable1 к базе данных, определим параметры диалога открытия изображений.

procedure TfrmMain.FormCreate(Sender: TObject); var s:string;

FT:TFileTypeItem;

const db='\blobdemo.accdb'; begin

{подключаемся к базе данных} s:=ExtractFilePath(Application.ExeName)+db; if FileAge(s)>0 then

begin

ADOTable1.ConnectionString:='Provider=Microsoft.ACE.OLEDB.12.0; Data Source='+s+';Persist Security In-

fo=False';

ADOTable1.TableName:='PICTURETABLE';

ADOTable1.Open;

GetData;

{настраиваем файловый диалог в стиле Vista} FT:=FileOpenDialog1.FileTypes.Add; FT.FileMask:='*.bmp'; FT.DisplayName:='Растровый файл';

end else begin

Application.MessageBox(pChar('Не найден файл'+#13+S),'Ошибка',MB_OK);

Application.Terminate; end;

end;

Выберите кнопку btnFirst, отвечающую за перевод курсора на самую первую запись в таблице и опишите её обработчик события OnClick(). Особенность события в том, что оно будет применяться для всех четырёх кнопок перемещения. Если помните, кнопки перемещения по записям таблицы различаются свойством tag, btnFirst – 0, btnPrior – 1,

© 2011 г. Д.Л. Осипов

95

btnNext – 2, btnLast – 3. Анализируя свойство tag в селекторе Case мы вызываем соответствующий метод таблицы.

procedure TfrmMain.btnFirstClick(Sender: TObject); begin

with ADOTable1 do

Begin

{перемещаем курсор в соответствии со значением свойства tag кнопок перемещения по записям}

case (sender as TComponent).Tag of

0:First; //на первую запись

1:Prior; //на предыдущую запись

2:Next; //на следующую запись

3:Last; //на последнюю запись набора данных

end;

GetData;//получаем данные из таблицы

{с помощью методов BOF и EOF проверяем местоположение текущей записи} btnFirst.Enabled:=NOT(BOF);{кнопка отключается,

если курсор на первой записи}

btnPrior.Enabled:=NOT(BOF); btnNext.Enabled:=NOT(EOF);{кнопка отключается,

если курсор на последней записи}

btnLast.Enabled:=NOT(EOF);

end;

end;

В заключении нам осталось описать действия добавления, редактирования и удаления записи.

procedure TfrmMain.btnAppendClick(Sender: TObject);//добавление begin

ADOTable1.Append; {добавление новой записи в конец набора} SetData; {вызов выбора изображения}

GetData; {передаём данные в компонент Image1 и StaticText1} end;

procedure TfrmMain.btnEditClick(Sender: TObject);//редактирование begin

ADOTable1.Edit;{перевод таблицы в режим редактирования} SetData;

GetData; end;

procedure TfrmMain.btnDeleteClick(Sender: TObject);//удаление begin

if MessageBox(frmMain.Handle, pWideChar('Удалить запись?'), pWideChar('Удаление'),

MB_YESNO + MB_ICONQUESTION)=idYes then

begin

{удаление записи}

ADOTable1.Delete;

Image1.Picture.Bitmap.FreeImage;

{освобождаем ресурс картинки}

StaticText1.Caption:='';

{очищаем заголовок метки}

GetData;

 

end;

 

end;

 

© 2011 г. Д.Л. Осипов