PiedSoftware 4 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) 3 hours ago, 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 1 hour ago, 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 4 Posted April 15 (edited) 15 hours ago, 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) 10 hours ago, 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 4 Posted Friday at 01:45 AM On 4/15/2025 at 2:19 AM, 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 Friday at 03:33 AM 1 hour ago, PiedSoftware said: Done. https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-3336 thanks Share this post Link to post
Rollo62 570 Posted 4 hours ago On 4/14/2025 at 7: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 4 Posted 4 hours ago (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 4 hours ago by PiedSoftware Share this post Link to post