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;
LVL 1
bogiboyAsked:
Who is Participating?
 
Lee_NoverCommented:

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

there :)
(borland might hate me for this getting out to those Delphi PE users :)
0
 
kretzschmarCommented:
? mysterious ... listening . . .
0
 
Lee_NoverCommented:
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
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
bogiboyAuthor Commented:
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..
0
 
bogiboyAuthor Commented:
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...
0
 
Lee_NoverCommented:
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
0
 
bogiboyAuthor Commented:
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?
0
 
kretzschmarCommented:
>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 ;-)
0
 
bogiboyAuthor Commented:
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?
0
 
Lee_NoverCommented:
:)

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);
0
 
bogiboyAuthor Commented:
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."
0
 
kretzschmarCommented:
>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 ;-)
0
 
Lee_NoverCommented:
>> 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
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.