Хранение OLE-объектов в базах данных. Использование памяти и методов-наследников класса TDataSet

   
На этом шаге мы рассмотрим еще один способ размещения в базе данных OLE-объекта.

   
Пример, приведенный на предыдущем шаге, имеет массу недостатков. Главным из них является тот факт,
что пользователь должен вручную инициировать загрузку содержимого BLOB-поля в компонент TOleContainег и сохранение
содержимого TOleContainer в таблице. Такое поведение приложения противоречит традиционному принципу создания пользовательских
интерфейсов для форм просмотра и редактирования данных, гласящему, что данные в интерфейсных элементах при перемещении по записям,
содержащимся в доставленном на рабочую станцию наборе данных, должны обновляться автоматически и сохраняться автоматически.

   
Если преодолеть первый недостаток данного приложения, добившись автоматического обновления данных в OLE-контейнере и сохранения
их в таблице, тут же проявится его второй недостаток, заключающийся в постоянном сохранении и загрузке данных с диска. Дисковые операции
вполне допустимы при ручных манипуляциях с OLE-коитейнером, но при автоматическом обновлении и сохранении они могут привести
к заметному снижению производительности приложения.

   
Реализуя принцип автоматического обновления и сохранения данных при выполнении навигационных методов компонентов TDataSet,
следует учитывать, что компонент TOleContainer не может быть связан с источником данных. Поэтому в простейшем случае необходимо
использовать методы BeforeScroll и AfterScroll компонента-наследника класса TDataSet. В обработчике события
BeforeScroll следует проверить, было ли изменено содержимое OLE-коитейпера. Это достигается путем проверки свойства
Modified компонента TOleContainer. Если в этом компоненте были произведены какие-либо изменения, то создается поток
данных в памяти, куда первоначально заносится некоторая последовательность байтов (назовем ее условно "цифровой подписью"; стоит, однако,
отдавать себе отчет в том, что к настоящей цифровой подписи эта последовательность байтов отношения не имеет). Подпись будет в дальнейшем
нужна при чтении данных: анализируя ее, можно определить, находятся ли данные для компонента TOleContainer в текущей записи.
Затем используется метод SaveToStream компонента TOleContainer:

const
  Signature: Integer = -525465623;
.    .     .     .
procedure TForm1.Table1BeforeScroll(DataSet: TDataSet);
var
  Stream: TMemoryStream;
begin
  if OleContainer1.Modified then
  begin
    Stream := nil;
    try
      Stream := TMemoryStream.Create;
      Stream.Write(Signature,SizeOf(Signature));
      if Assigned(OleContainer1.OleObjectInterface) then
        OleContainer1.SaveToStream(Stream);
      Stream.Seek(0, soFromBeginning);
      try
        Table1.Edit;
        TBLOBField(Table1.FieldByName('Graphic')).
           LoadFromStream(Stream);
        Table1.Post;
        OleContainer1.Modified := False;
      except
        Table1.Cancel;
      end;
      finally
        if Assigned(Stream) then Stream.Free;
    end;
  end;
end;

procedure TForm1.Table1AfterScroll(DataSet: TDataSet);
var
  Stream: TMemoryStream;
  N: Integer;
begin
  OleContainer1.DestroyObject;
  Stream := nil;
  try
    Stream := TMemoryStream.Create;
    TBLOBField(Table1.FieldByName('Graphic')).SaveToStream(Stream);
    Stream.Seek(0, soFromBeginning);
    if Stream.Size > 4 then
    begin
       Stream.Read(N, SizeOf(N));
       if N = Signature then
          OleContainer1.LoadFromStream(Stream);
    end;
    OleContainer1.Modified := False;
  finally
    if Assigned(Stream) then Stream.Free;
  end;
end;

Текст этого приложения со всеми дополнительными файлами можно взять здесь (257 Кб).

   
В заархивированной базе данных biolife.db содержимое поя Graphic у первых двух записей изменено.
На рисунке 1 приведено содержимое этого поля у второй записи.


Рис.1. Результат работы приложения

   
Прежде всего обработчик события AfterScroll очищает текущее содержимое OLE-контейнера. После этого создается поток
данных в памяти, куда и переносится содержимое BLOB-поля. Затем следует удостовериться, что поток данных содержит более 4 байт
информации (иначе в нем не поместится даже "цифровая подпись"). После этого производится чтение "цифровой подписи" и при ее совпадении
со значением константы Signature производится загрузка данных и установка свойства Modified равным False,
что позволяет корректно определить, были ли произведены изменения содержимого OLE-контейнера после загрузки данных.

   
На следующем шаге мы рассмотрим создание OLE-контейнера в виде VCL-компонента.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий