• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 359
  • Last Modified:

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;
0
bogiboy
Asked:
bogiboy
  • 5
  • 5
  • 3
1 Solution
 
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
 
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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

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:
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
 
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
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.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now