PiedSoftware 5 Posted April 14 Hi It seems like a natural thing to want: is there a way to get all the datasouces that have dataset = ADataset? Other than looping through the components property of the owner of course. I was looking at the code of TDataset. It even has a private member variable FDatasources: TList<TDatasource>, but it is not exposed. So close! TIA Mark 1 Share this post Link to post
Patrick PREMARTIN 121 Posted April 14 (edited) Perhaps you can try to access it from a helper on TDataSet... Edited April 14 by Patrick PREMARTIN Share this post Link to post
Remy Lebeau 1572 Posted April 14 (edited) On 4/14/2025 at 11:00 AM, Patrick PREMARTIN said: Perhaps you can try to access it from a helper on TDataSet... Class helpers don't have access to private members anymore since Delphi 10.1 Berlin. https://blogs.embarcadero.com/closing-the-class-helpers-private-access-loophole/ Edited April 14 by Remy Lebeau 1 Share this post Link to post
Patrick PREMARTIN 121 Posted April 14 On 4/14/2025 at 2:43 PM, Remy Lebeau said: Class helpers don't have access to private members anymore since Delphi 10.1 Berlin. https://blogs.embarcadero.com/closing-the-class-helpers-private-access-loophole/ Ah, yes, I've forgotten that. So no other solution than RTTI or checking all components in loops. Mark, you're probably not the first one in 30 years to want to access it. Perhaps you can open a "new feature" request on https://qp.embarcadero.com asking for having DataSources[] (read only) and DataSourceCount public properties on TDataSet ? (and explain why you need them) Share this post Link to post
PiedSoftware 5 Posted April 15 (edited) On 4/14/2025 at 11:00 AM, Patrick PREMARTIN said: Perhaps you can try to access it from a helper on TDataSet... I don't know if it has the right meaning though. And since in Delphi there can only be one helper, I would avoid that approach in case someone else had a better use for it. Edited April 15 by PiedSoftware Share this post Link to post
Keesver 25 Posted April 15 As a last resort you can define your own TDataset type with a public 'FDatasource' member and then cast the TDataset to this type. Design wise this is a clear 'hack' but it will do the job: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient, Vcl.StdCtrls, System.Generics.Collections; type TForm1 = class(TForm) ClientDataSet1: TClientDataSet; Button1: TButton; DataSource1: TDataSource; DataSource2: TDataSource; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; THackedDataSet = class(TComponent) public FFields: TFields; FAggFields: TFields; FFieldDefs: TFieldDefs; FFieldDefList: TFieldDefList; FFieldList: TFieldList; FDataSources: TList<TDataSource>; end; PHackedDataSet = ^THackedDataSet; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin var ds := PHackedDataSet(@ClientDataSet1)^; ShowMessage(ds.Name); for var src in ds.FDataSources do ShowMessage(src.Name); end; end. Share this post Link to post
Remy Lebeau 1572 Posted April 15 (edited) On 4/15/2025 at 6:05 AM, Keesver said: As a last resort you can define your own TDataset type with a public 'FDatasource' member and then cast the TDataset to this type. Design wise this is a clear 'hack' but it will do the job That approach is dependent on the layout of the original class, and could break between updates, so use with caution. It is also not a last resort, either. A safer approach would be to use RTTI to get the offset of the desired class member, and then use pointer arithmetic to access the member, eg: uses ..., System.Rtti; private DataSourcesOffset: Integer; ... procedure TForm1.Form1Create(Sender: TObject); var Ctx: TRttiContext; begin DataSourcesOffset := Ctx.GetType(TClientDataSet).GetField('FDataSources').Offset; end; procedure TForm1.Button1Click(Sender: TObject); type PDataSourceList = ^TList<TDataSource>; begin var ds := PDataSourceList(PByte(ClientDataSet1) + DataSourcesOffset)^; for var src in ds do ShowMessage(src.Name); end; Edited April 15 by Remy Lebeau Share this post Link to post
PiedSoftware 5 Posted April 18 On 4/14/2025 at 4:19 PM, Patrick PREMARTIN said: Mark, you're probably not the first one in 30 years to want to access it. Perhaps you can open a "new feature" request on https://qp.embarcadero.com asking for having DataSources[] (read only) and DataSourceCount public properties on TDataSet ? (and explain why you need them) Done. https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-3336 Share this post Link to post
Patrick PREMARTIN 121 Posted April 18 On 4/18/2025 at 1:45 AM, PiedSoftware said: Done. https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-3336 thanks Share this post Link to post
Rollo62 571 Posted Tuesday at 05:56 AM On 4/14/2025 at 5:43 AM, PiedSoftware said: ... It seems like a natural thing to want: is there a way to get all the datasouces that have dataset = ADataset? .... I also understand the urge to have such handy property, for convenience. On the other hand, if I consider the DataSource as part of the view and the Dataset as part of the model, perhaps there is a good reason to hide it here, so that the model doesn't know about its views. Share this post Link to post
PiedSoftware 5 Posted Tuesday at 06:25 AM (edited) Rollo62: Yes, there is a way to see it like that. I can't think of another more theoretically pure place to put it, unless the datasources were all under some manager at the application level. But the fact is that both are declared in Data.DB, and TDataset already has a member variable of type FDataSources: TList<TDataSource> and property DataSource: TDataSource, used for setting indexes or something. Edited Tuesday at 06:26 AM by PiedSoftware 1 Share this post Link to post