Link to home
Start Free TrialLog in
Avatar of bogiboy
bogiboy

asked on

Destroying TMemoryStream

I have BLOB field where I store documents from OleContainer (streams). Later on, I can use OleContainer to open and modify document. How I do that:
1. Declare str:TMemoryStream on the Form level
2. On btnOpenClick I create str:TMemoryStream, read the value from BLOB field, put it in OleContainer as stream, open Ole (DoVerb) object, modify it and update OleContainer.
3.Then on btnSaveClick, I use the same stream "str" (created in another procedure but declared on form-level) to update Blob field.

Question/Problem: I noticed that if I try to destroy the "str" (str.Free) after calling myAdoDataSet.Post, it will not post the changes and I got error "dataset not in edit or insert mode". But, if I don't Free the stream then it's fine. ??? Why? Is it safe to do this way, will my "str" object be Killed when I close the form?

Here is the "save to database" code:

begin
if (rst.State=dsEdit) then
begin
str.Clear;

ole1.SaveToStream(str);
rst.Edit;
TBlobField(rst.FieldByName('Document')).LoadFromStream(str);
showmessage(inttostr(str.size));
rst.Post;
//if assigned(str) then str.Free;
end;
rst.Close;
ole1.DestroyObject;
end;
Avatar of kretzschmar
kretzschmar
Flag of Germany image

? mysterious ... listening . . .
Avatar of Lee_Nover
Lee_Nover

yous should try rst.FlushBuffers; that writes data to disk


I never liked .FieldByName
it searches through all the fields to find the proper one
I rather use desingtime field creation
doubleclick the dataset and Add new fields
so you get a new object like : rstBlobField: TBlobField;

then you simply use rstBlobField.LoadFromStream(str);
that has always worked for me
and this was also a solution for one of the questions on EE
the coder used the same method as you and had similar problems
with my method it worked :)
try it out
Avatar of bogiboy

ASKER

Strange, strange, strange...
Instead of rst.Free I tried with rst:=nil and IT WORKS!?
Hm...Why?
BTW, I use ADO so FlushBuffers is not applicable..
Avatar of bogiboy

ASKER

Sorry, I made mistake, it was not rst:=nil but str:=nil...So if I dispose stream using str:=nil, I don't get an error...
that way you don't free it's memory !
you simply set the str reference to nil
the actual stream is still in memory
try my suggestion
Avatar of bogiboy

ASKER

No, no, I tried your suggestion and created persistent fields, but still doesn't work- error is poping up "dataset not in insert or edit mode". What you are saying is that if I use myStream:=nil it will be still in the memory? Will it be destroyed when I dereference form where it is declared?
>it will be still in the memory?
yes

>Will it be destroyed when I dereference form where it is declared?
no, only free or destroy does this job (free is the reommended method)

meikl ;-)
Avatar of bogiboy

ASKER

I am confused now with this:

...
if assigned(str) then
begin
str:=nil;
str.Free;
end;
...
and I am not getting error now??? And my document in DB is updated! Opinions?
:)

first you set it's reference to nil
then you try to free it
but .Free check if the object is nil
if it's nil then it does nothing !!!

about my method .. did you do :

// load the ole into str
rst.Edit;
rstBlobField.LoadFromStream(str);
rst.Post;
FreeAndNil(str);
Avatar of bogiboy

ASKER

No Lee, I created persistent fields ("Add all fields...") and did exactly as you suggested- and still nothing.
Speaking of nil and Free:
In help, i found that Free is a safe way do destroy objects because Destroy doesn't check if object is nil - Free does. But it also says that for Free it doesnt't matter if object is nil or not, it will destroy it. Did I misunderstood this paragraph?

From Help>TObject>Free:

"Use Free to destroy an object. Free automatically calls the destructor if the object reference is not nil. Any object instantiated at runtime that does not have an owner should be destroyed by a call to Free so that it can be properly disposed of and its memory released. Unlike Destroy, Free is successful even if the object is nil; so if the object was never initialized, Free won’t result in an error."
>Free automatically calls the destructor if the object reference is not nil

the destructor is never called, if u use this
str:=nil;
str.Free;
the object still remains in memory
and you have lost its reference

still cannot reproduce your problem

meikl ;-)
>> Unlike Destroy, Free is successful even if the object is nil; so if the object was never initialized, Free won’t result in an error.

it's merely saying that free will always work - meaning it will not produce an error if the object is nil as destroy would

well you might think of a global stream :)
create when the form is created and free when the form is destroyed
ASKER CERTIFIED SOLUTION
Avatar of Lee_Nover
Lee_Nover

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial