I am using Delphi6
and have a data module with an ADO
DataSet
which is used by two forms, formA and FormB. Each form has a Dataset.Open()
in OnCreate
and Dataset.Close()
in OnClose
. If both forms are open simultaneously and formB is closed the dataset is closed in formA. How can I prevent this, essentially I need separate instances of the dataset for each form but at the same time use the datamodule.
问题:
回答1:
The simplest way to achieve what you want is to create an instance of the data module for each form, and pass it to the form so it can be freed when the form is closed:
var
Data: TDataModule;
begin
Data := T<YourDataModule>.Create(Self);
try
Form := T<YourForm>.Create(Self);
Form.DataModule := Data;
Data.Name := '';
except
Data.Free;
raise;
end;
Form.Show;
end;
Setting the DataModule's Name to an empty string is done to ensure that the VCL's logic for hooking up data aware controls to their datasource/dataset is done using the newly created instance, instead of the first ever instance.
In the Form's OnClose handler (or its destructor) make sure to free the data module.
回答2:
Probably you need a separate instance from the datamodule for each form.
If you really want to use the same datamodule instance form both forms, then you have to open and close the dataset from the datamodule, adding some reference counting mechanism.
Tipically you do that by having a procedure for opening the dataset and one for closing it in the datamodule and an integer to count the open and close calls. The procedure which opens the dataset actually opens it only at the first call, at any subsequent call just incremets the counter. The closer procedure decrements the counter at each call, and closes the database when the counter value drops back to 0.
回答3:
Are you trying to access the same dataset from FormA and FormB at the same time while displaying different data, if so:
Use a TClientDataSet and a TDataSetProvider to load the data from you ADO dataset. Then clone the cursor using ClientDataSet.CloneCursor, you get a seperate cursor to the same data. Then pass them to the forms or assign the controls of FormA to ClientDataSetA and FormB to the clone ClientDataSetB. Reads, writes and updates from both forms change the underlying dataset which can then apply the updates to the database through the ADO dataset later via the DataSetProviders ApplyUpdates.
Look here for some help: http://www.podgoretsky.com/ftp/docs/Delphi/D5/dg/5_ds3.html Or there is a really good book by Cary Jenson: http://www.jensendatasystems.com/cdsbook/ (free plug, but it is a good read)
回答4:
As you said you need seperate instances, then my solution would be to have a Datamodule variable in each form declaration:
TForm1 = class(TForm)
...
private
fDatamodule : TDatamodule1;
...
end;
procedure TForm1.FormCreate(Sender : TObject)
begin
fDatamodule := TDatamodule1.Create(self);
MyDatasource.Dataset := fDatamodule.MyDataset;
end;
(repeat for Form2 etc)
You have the same datamodule, instanciated twice and thus completely seperate from each other, but utilising the same business logic in each form.
Whilst on the subject, ensure your datamodule code does not make reference to either form. This is bad practice.