You are not logged in.
Hello time ago I asked you about fillprepare and FillRow, see link http://synopse.info/forum/viewtopic.php?id=188.
I eventually used "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS)," to create a "resultset", I used "Client.Update (Rec)" and "Client.UpdateFromServer ([Table], Refreshed);" to update a records on the server and display the result in a quantumgrid and up to here everything is working.
Now I have the problem that if I add a record to the table "TSQLFile" I'm forced to run again "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS);" to view data in the grid, then I ask you can I not run a ResultSet.Add and then ResultSet.Refresh.
I ask this because FLDS is a "FIDS: TIntegerDynArray," is the result of a non-functioning, which is cumbersome if you have to run every Add, Remove the recordset
Thanks, sorry for my english.
Offline
My code is:
{ TSQLFile }
class function TSQLFile.LoadFilesForQvw(ClientDB: TSQLRestClientUri;const AQvw: TSQLQvw):TSQLFile;
var
fIds: TIntegerDynArray;
begin
result := nil;
AQvw.Files.DestGet(ClientDB, AQvw.ID, fIds);
if Length(fIds)>0 then
begin
result := TSQLFile.CreateAndFillPrepare(ClientDB, fIds);
end
else
result := TSQLFile.CreateAndFillPrepare(ClientDB,'Owner = '''+ AQvw.Name+'''');
end;
......
procedure TFrmToolBarMain.ActFiltersExecute(Sender: TObject);
var
AFile: TSQLFile;
begin
Try
FileDlg := TFileDlg.Create(self) ;
AFile:= TSQLFile.LoadFilesForQvw( currentClient ,currentQvw);
if Assigned(AFile) then
begin
FileDlg.SetTable(currentClient,currentQvw,currentUser,AFile);
FileDlg.ShowModal;
end;
finally
FreeAndNil(FileDlg);
end;
end;
....
procedure TFileDlg.ActAddExecute(Sender: TObject);
var
aRec: TSQLFile;
newID:Integer;
refreshed:Boolean;
FileDS : TFileDatasource;
begin
inherited;
aRec:= TSQLFile.Create;
try
aRec.Owner := AQvw.Name;
aRec.Created := Iso8601Now;
aRec.Modified := aRec.Created;
newID:= ADatabase.Add(aRec,true);
aRec.Name := format('File%d', [newID]);
AQvw.Files.ManyAdd(ADatabase,AQvw.ID,newID,true);
Edit(aRec,'Add',false);
finally
FreeAndNil(aRec);
end;
//Here I am forced to run "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS)," otherwise I do not see the new "ID" (inserted record)
try
tb.BeginUpdate;
fRec:= TSQLFile.LoadFilesForQvw( currentClient ,currentQvw);
FileDS := TFileDatasource.Create(tb, ADatabase,fRec);
tb.DataController.CustomDataSource := FileDS;
finally
tb.EndUpdate;
end;
end;
Offline
Due to the stateless approach of the framework, there is indeed no automated reflection of the newly inserted record in the fIDs[] array.
Since all records content will already be stored as a TSQLTableJSON, you can't by design add an individual record to the list. All new list should be retrieved, by calling CreateAndFillPrepare one more time.
Is it too slow in practice? I don't think so.
Offline
You're right for the example above is fast,
but the below example becomes slower .
In the following example, I have to filter "TSQLFile" for users, roles, and groups.
It is very heavy to run every time that i add a new record.
class function TSQLQvw.LoadQvwsForUser(ClientDB: TSQLRestClientUri;const AUser: TSQLUser;Onlypublished:Boolean=false ):TSQLQvw;
var
fIds,fIds2,fIds3,fIds4,fIds5: TIntegerDynArray;
ARole: TSQLRole;
AGruppo :TSQLGruppo;
i:Integer;
fIdsIndexCount: integer;
function checkPublished(ID:Integer):boolean;
var
AQvw:TSQLQvw;
begin
result := false;
try
AQvw := TSQLQvw.Create;
if ClientDB.Retrieve(ID,AQvw) then
result := AQvw.Owner<>AUser.Name;
finally
AQvw.Free;
end;
end;
begin
result := nil;
fIdsIndexCount := 0;
AUser.File.DestGet(ClientDB, AUser.ID, fIds);
// for I := 0 to Length(fIds) - 1 do
// AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
CopyAndSortInteger(Pointer(fIds),Length(fIds),fIds4);
AUser.Groups.FillMany(ClientDB, AUser.ID);
while AUser.Groups.FillOne do
begin
if AUser.Groups.Dest <> nil then
try
AGruppo:= TSQLGruppo.Create(ClientDB, integer(AUser.Groups.Dest));
AGruppo.File.DestGet(ClientDB, AGruppo.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
AGruppo.Roles.FillMany(ClientDB, AGruppo.ID);
while AGruppo.Roles.FillOne do
begin
if AGruppo.Roles.Dest <> nil then
try
ARole:= TSQLRole.Create(ClientDB, integer(AGruppo.Roles.Dest));
ARole.File.DestGet(ClientDB, ARole.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
finally
FreeAndNil(ARole);
end;
end;
finally
FreeAndNil(AGruppo);
end;
end;
AUser.Roles.FillMany(ClientDB, AUser.ID);
while AUser.Roles.FillOne do
begin
if AUser.Roles.Dest <> nil then
try
ARole:= TSQLRole.Create(ClientDB, integer(AUser.Roles.Dest));
ARole.File.DestGet(ClientDB, ARole.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
finally
FreeAndNil(ARole);
end;
end;
if Onlypublished then
begin
for I := Length(fIds4)-1 downto 0 do
begin
if not checkPublished(fIds4[i]) then
begin
DeleteInteger(fIds4,i);
end;
end;
end;
if Length(fIds4)>0 then
begin
result := TSQLQvw.CreateAndFillPrepare(ClientDB, fIds4);
end
else
result := TSQLQvw.CreateAndFillPrepare(ClientDB,'Owner = '''+ AUser.Name+'''')
end;
Offline
You're right for the example above is fast,
but the below example becomes slower .
In the following example, I have to filter "TSQLFile" for users, roles, and groups.
It is very heavy to run every time that i add a new record.
class function TSQLQvw.LoadQvwsForUser(ClientDB: TSQLRestClientUri;const AUser: TSQLUser;Onlypublished:Boolean=false ):TSQLQvw;
var
fIds,fIds2,fIds3,fIds4,fIds5: TIntegerDynArray;
ARole: TSQLRole;
AGruppo :TSQLGruppo;
i:Integer;
fIdsIndexCount: integer;
function checkPublished(ID:Integer):boolean;
var
AQvw:TSQLQvw;
begin
result := false;
try
AQvw := TSQLQvw.Create;
if ClientDB.Retrieve(ID,AQvw) then
result := AQvw.Owner<>AUser.Name;
finally
AQvw.Free;
end;
end;
begin
result := nil;
fIdsIndexCount := 0;
AUser.File.DestGet(ClientDB, AUser.ID, fIds);
// for I := 0 to Length(fIds) - 1 do
// AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
CopyAndSortInteger(Pointer(fIds),Length(fIds),fIds4);
AUser.Groups.FillMany(ClientDB, AUser.ID);
while AUser.Groups.FillOne do
begin
if AUser.Groups.Dest <> nil then
try
AGruppo:= TSQLGruppo.Create(ClientDB, integer(AUser.Groups.Dest));
AGruppo.File.DestGet(ClientDB, AGruppo.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
AGruppo.Roles.FillMany(ClientDB, AGruppo.ID);
while AGruppo.Roles.FillOne do
begin
if AGruppo.Roles.Dest <> nil then
try
ARole:= TSQLRole.Create(ClientDB, integer(AGruppo.Roles.Dest));
ARole.File.DestGet(ClientDB, ARole.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
finally
FreeAndNil(ARole);
end;
end;
finally
FreeAndNil(AGruppo);
end;
end;
AUser.Roles.FillMany(ClientDB, AUser.ID);
while AUser.Roles.FillOne do
begin
if AUser.Roles.Dest <> nil then
try
ARole:= TSQLRole.Create(ClientDB, integer(AUser.Roles.Dest));
ARole.File.DestGet(ClientDB, ARole.ID, fIds);
fIdsIndexCount := Length(fIds4);
for I := 0 to Length(fIds) - 1 do
AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
finally
FreeAndNil(ARole);
end;
end;
if Onlypublished then
begin
for I := Length(fIds4)-1 downto 0 do
begin
if not checkPublished(fIds4[i]) then
begin
DeleteInteger(fIds4,i);
end;
end;
end;
if Length(fIds4)>0 then
begin
result := TSQLQvw.CreateAndFillPrepare(ClientDB, fIds4);
end
else
result := TSQLQvw.CreateAndFillPrepare(ClientDB,'Owner = '''+ AUser.Name+'''')
end;
Offline
I guess in this case, you'll have to write a dedicated SQL query, then execute it and retrieve all data using a TSQLTableJSON.
It should be much faster than all ORM-based process.
This is the limit of ORM, and, as stated by the documentation, it could be a proper occasion to switch back to SQL.
Offline