Streaming Data to Blob Fields
If you are reading this article you have probably discovered that reading and writing to and from BLOB fields is not as straight forward as their counterparts, integer and character. The wonderful implicit assignments to integer and character fields just don't exist. Don't despair. Accessing data in a BLOB is not as simple as other field types, but is by no means difficult.
TBLOBStream
The main difference in accessing BLOB data is the use of streams for the actual data transfer. Once you have a reference to your Dataset's BLOB field, you open a stream to it by passing that reference to TBLOBStream's Create method. TBLOBStream descends from TStream and encapsulates the operations that allow your applications to read from or write to Binary Large Object(BLOB) fields.
There are a few things that you should take into consideration when creating your BLOB streams(s). One is that you should make sure to create a new instance of TBLOBStream for every field you plan to read from and free it when you are done. That other is that even though TBLOBStream lets you create instances of it to use with any kind of DataSet, it is best to instead call the particular DataSet's CreateBLOBStream method. It works exactly like TBLOBStream.Create, but it instantiates an object specific for that Dataset(TTable,TQuery). My examples will uses this method.
A Simple Example: Streaming Bitmaps
While BLOBs can hold many different kinds of data, including MEMOs and... well just about anything you want, my example will focus on the streaming of bitmap files. These concepts hold true for all types of data.
Using the BDE
First, start a new Delphi application and drop on your database components for your connection. This will include a TDataBase and TQuery. Hook your Query to your Database object and set it's RequestLive property to true, since we will be inserting data. Now we will write your bitmap image to you database field. First we will want a Bitmap to work with. After declaring a TBitmap, create it and load a file with your favorite picture into it.
MyFavoriteBitmap := TBitmap.Create;
MyFavoriteBitmap.LoadFromFile('drive:pathMyFavoriteBitmap.bmp');
Once you have a Bitmap ready and waiting, you can go ahead and create your BLOB stream. To do this, you will need to get a reference to your blobfield from the query. If you know the name for the field, TDataSet.FindByName is the easiest. Now Pass this reference into CreateBLOBStream along with the BlobStreamMode(bmRead,bmWrite,bmReadWrite), which will return reference to a TStream. We are going to use this to actually stream the file using TBitmap's SaveToStream method.
procedure SavePictureToDatabase;
var
BlobField: TField;
BS: TStream;
begin
with Query1 do
begin
Insert;
BlobField := FieldByName('picturefield');
BS := CreateBlobStream(BlobField,bmWrite);
Bitmap.SavetoStream(BS);
Post;
end;
end;
Using dbExpress
Those of you using the new dbExpress components will find the process is identical with a few minor exceptions. If you are using TSQLQuery or TSQLTable, you are enjoying their extremely fast execution for your reporting applications. But since they do not cache their data, their is no way for you to edit any records, let alone your BLOBS. Don't forget that you must use TSQLClientDataSet instead of TSQLDataSet's to achieve this functionality. In code, the difference is trivial for writing yourt picture to a database.
procedure SavePictureToDatabase;
var
BlobField: TField;
BS: TStream;
begin
with SQLClientDataSet1 do
begin
Insert;
BlobField := FieldByName('picturefield');
BS := CreateBlobStream(BlobField,bmWrite);
Bitmap.SavetoStream(BS);
Post;
end;
end;
When you are ready to read you bitmap back out, use the built in TBitmap method and you are set.
Blobfield := FieldbyName('picturefield');
BS := CreateBlobStream(BlobField,bmReadWrite);
MyFavoriteBitmap.LoadFromStream(BS);
Other types of binary data
When moving in large chunks of data that do not have convenient loading and saving methods like TBitmap, you must employ the TStream methods (Read, ReadBuffer, Write, WriteBuffer) manually. You can even stream components and their properties using WriteComponent and ReadComponent, were you so inclined.
var
MyComponent: TMyComponent //any TComponent
begin
MyComponent := TMyComponent.Create;
MyComponent.aProperty := aValue;
BS := CreateBlobStream(Blobfield,bmReadWrite);
BS.WriteComponent(MyComponent);
end;
There you have it. A quick intro to using BLOBs to store binary data. I think the moral of the story is quite clear: Don't take candy from strangers', kids.