Jump to content

MyDAC with UNIGUI ... Locate ... problem


gerardocrisci

Recommended Posts

I have a problem using MyDAC (10.4.4) with UNIGUI.
When using Locate before displaying the form, the record selected on the uniDBgrid is always the first, the cursor does not move.

If the same operation is done at the click of a button ... the cursor moves ... and it works.

procedure TMainForm.MySearch(V:string);
begin
  if MyQuery1.Locate('ID',V,[]) then
    UniLabel1.Caption:='FOUND :'+V;
end;

procedure TMainForm.UniFormAfterShow(Sender: TObject);
begin
  MySearch('12'); //Finds the record, but does not display it in the grid
end;

procedure TMainForm.UniButton2Click(Sender: TObject);
begin
  MySearch('30'); //Find the recod and it is displayed in the grid.
end;

With this problem I cannot select the record before the unidbgrid is displayed.

Do you have a solution?

Link to comment
Share on other sites

42 minutes ago, gerardocrisci said:

I have a problem using MyDAC (10.4.4) with UNIGUI.
When using Locate before displaying the form, the record selected on the uniDBgrid is always the first, the cursor does not move.

If the same operation is done at the click of a button ... the cursor moves ... and it works.

procedure TMainForm.MySearch(V:string);
begin
  if MyQuery1.Locate('ID',V,[]) then
    UniLabel1.Caption:='FOUND :'+V;
end;

procedure TMainForm.UniFormAfterShow(Sender: TObject);
begin
  MySearch('12'); //Finds the record, but does not display it in the grid
end;

procedure TMainForm.UniButton2Click(Sender: TObject);
begin
  MySearch('30'); //Find the recod and it is displayed in the grid.
end;

With this problem I cannot select the record before the unidbgrid is displayed.

Do you have a solution?

You should locate onAfterLoad event to make sure data is ready.

Link to comment
Share on other sites

1 hour ago, Hayri ASLAN said:

Can you please create a test case?

simple example
Mainform with MyConnection1, MyQuery1, MyDataSource1

Main.pas

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIRegClasses, uniGUIForm, uniLabel, uniButton,
  uniGUIBaseClasses, uniBasicGrid, uniDBGrid, Data.DB, DBAccess, MyAccess, MemDS;

type
  TMainForm = class(TUniForm)
    MyConnection1: TMyConnection;
    MyQuery1: TMyQuery;
    MyDataSource1: TMyDataSource;
    UniDBGrid1: TUniDBGrid;
    UniButton1: TUniButton;
    UniLabel1: TUniLabel;
    procedure UniButton1Click(Sender: TObject);
    procedure UniFormAfterShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure MySearch(V:string);
  end;

function MainForm: TMainForm;

implementation

{$R *.dfm}

uses
  uniGUIVars, MainModule, uniGUIApplication;

function MainForm: TMainForm;
begin
  Result := TMainForm(UniMainModule.GetFormInstance(TMainForm));
end;

procedure TMainForm.MySearch(V:string);
begin
  if MyQuery1.Locate('country_id',V,[]) then
    UniLabel1.Caption:='FOUND :'+V;
end;

procedure TMainForm.UniFormAfterShow(Sender: TObject);
begin
   MySearch('4'); //Finds the record, but does not display it in the grid
end;

procedure TMainForm.UniButton1Click(Sender: TObject);
begin
   MySearch('5'); //Find the recod and it is displayed in the grid.
end;

initialization
  RegisterAppFormClass(TMainForm);

end.

Main.dfm

object MainForm: TMainForm
  Left = 0
  Top = 0
  ClientHeight = 299
  ClientWidth = 635
  Caption = 'MainForm'
  OldCreateOrder = False
  MonitoredKeys.Keys = <>
  OnAfterShow = UniFormAfterShow
  PixelsPerInch = 96
  TextHeight = 13
  object UniDBGrid1: TUniDBGrid
    Left = 20
    Top = 25
    Width = 386
    Height = 246
    Hint = ''
    DataSource = MyDataSource1
    LoadMask.Message = 'Loading data...'
    TabOrder = 0
  end
  object UniButton1: TUniButton
    Left = 435
    Top = 90
    Width = 75
    Height = 25
    Hint = ''
    Caption = 'UniButton1'
    TabOrder = 1
    OnClick = UniButton1Click
  end
  object UniLabel1: TUniLabel
    Left = 440
    Top = 130
    Width = 46
    Height = 13
    Hint = ''
    Caption = 'UniLabel1'
    TabOrder = 2
  end
  object MyConnection1: TMyConnection
    Database = 'sakila'
    Username = 'root'
    Server = 'localhost'
    Connected = True
    LoginPrompt = False
    Left = 440
    Top = 20
    EncryptedPassword = ''
  end
  object MyQuery1: TMyQuery
    Connection = MyConnection1
    SQL.Strings = (
      'select * from country')
    Active = True
    Left = 180
    Top = 125
  end
  object MyDataSource1: TMyDataSource
    DataSet = MyQuery1
    Left = 260
    Top = 125
  end
end

image.png.4203d6fcb6ada7679d8aef5aa5c84be0.png

at startup it does not go to record # 4
this does not work with MyDAC

 

 

Link to comment
Share on other sites

5 hours ago, gerardocrisci said:

simple example
Mainform with MyConnection1, MyQuery1, MyDataSource1

Main.pas

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIRegClasses, uniGUIForm, uniLabel, uniButton,
  uniGUIBaseClasses, uniBasicGrid, uniDBGrid, Data.DB, DBAccess, MyAccess, MemDS;

type
  TMainForm = class(TUniForm)
    MyConnection1: TMyConnection;
    MyQuery1: TMyQuery;
    MyDataSource1: TMyDataSource;
    UniDBGrid1: TUniDBGrid;
    UniButton1: TUniButton;
    UniLabel1: TUniLabel;
    procedure UniButton1Click(Sender: TObject);
    procedure UniFormAfterShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure MySearch(V:string);
  end;

function MainForm: TMainForm;

implementation

{$R *.dfm}

uses
  uniGUIVars, MainModule, uniGUIApplication;

function MainForm: TMainForm;
begin
  Result := TMainForm(UniMainModule.GetFormInstance(TMainForm));
end;

procedure TMainForm.MySearch(V:string);
begin
  if MyQuery1.Locate('country_id',V,[]) then
    UniLabel1.Caption:='FOUND :'+V;
end;

procedure TMainForm.UniFormAfterShow(Sender: TObject);
begin
   MySearch('4'); //Finds the record, but does not display it in the grid
end;

procedure TMainForm.UniButton1Click(Sender: TObject);
begin
   MySearch('5'); //Find the recod and it is displayed in the grid.
end;

initialization
  RegisterAppFormClass(TMainForm);

end.

Main.dfm

object MainForm: TMainForm
  Left = 0
  Top = 0
  ClientHeight = 299
  ClientWidth = 635
  Caption = 'MainForm'
  OldCreateOrder = False
  MonitoredKeys.Keys = <>
  OnAfterShow = UniFormAfterShow
  PixelsPerInch = 96
  TextHeight = 13
  object UniDBGrid1: TUniDBGrid
    Left = 20
    Top = 25
    Width = 386
    Height = 246
    Hint = ''
    DataSource = MyDataSource1
    LoadMask.Message = 'Loading data...'
    TabOrder = 0
  end
  object UniButton1: TUniButton
    Left = 435
    Top = 90
    Width = 75
    Height = 25
    Hint = ''
    Caption = 'UniButton1'
    TabOrder = 1
    OnClick = UniButton1Click
  end
  object UniLabel1: TUniLabel
    Left = 440
    Top = 130
    Width = 46
    Height = 13
    Hint = ''
    Caption = 'UniLabel1'
    TabOrder = 2
  end
  object MyConnection1: TMyConnection
    Database = 'sakila'
    Username = 'root'
    Server = 'localhost'
    Connected = True
    LoginPrompt = False
    Left = 440
    Top = 20
    EncryptedPassword = ''
  end
  object MyQuery1: TMyQuery
    Connection = MyConnection1
    SQL.Strings = (
      'select * from country')
    Active = True
    Left = 180
    Top = 125
  end
  object MyDataSource1: TMyDataSource
    DataSet = MyQuery1
    Left = 260
    Top = 125
  end
end

image.png.4203d6fcb6ada7679d8aef5aa5c84be0.png

at startup it does not go to record # 4
this does not work with MyDAC

 

 

I can't see MyQuery1.open

Where do you open your DataSet ?  OnCreate event ?

Link to comment
Share on other sites

8 hours ago, Abaksoft said:

I can't see MyQuery1.open

Where do you open your DataSet ?  OnCreate event ?

DFM

  object MyQuery1: TMyQuery
    Connection = MyConnection1
    SQL.Strings = (
      'select * from country')
    Active = True
    Left = 180
    Top = 125
  end

 

This is in the example ... but you can open it wherever you want .. the problem is the positioning of the row in the grid after the initial locate.

Link to comment
Share on other sites

The Locate method is intended to search for a record; the IndexFieldNames property is intended to sort records on the client.
These operations are only performed after fetching all data matching the query.

Maybe the problem is that,- at the moment you execute the code, NOT ALL RECORDS are loaded because
of TMyQuery.FetchAll = false. Then only the amount of records are loaded which is se by TMyQuery.FetchRows

When you you execute code by button maybe all or more records are loaded on that point.

So ....set the TMyQuery.FetchAll property to True;
and see if it changes the behavior.
 

Regards

 

 

Link to comment
Share on other sites

I did a simple test within my existing application which uses forms and frames.
The frame contains the dbgrid so i tested is like this in the uniFrameCreate event i put this simple code:

var
  P : Integer;
begin
 if not dmType.TypeCountry.Active then
          dmType.TypeCountry.Active;
          dmtype.TypeCountry.Open;
          P := 5;
         dmType.TypeCountry.Locate('typeCountryID', P, []);

Result is the record pointer is to the record with ID=5, see blue line in dbgrid...WORKS

Make sure that the variable you use is of type integer!

 

dbgrid.thumb.png.c50a78ee3f3ea0814f1085f2545e9929.png

 

 

Link to comment
Share on other sites

13 minutes ago, mierlp said:

Make sure that the variable you use is of type integer!

Have you done the test with MyDAC?😱
With FireDAC or ODBC or whatever it works.

From the example it is not a question of variable, the record finds it but does not display it.

Link to comment
Share on other sites

See testcase

  • in MainModule i put the MyConnection component and there you can use you're credentials to connect to you're mysql server
  • mainform contains the query and dataset component
  • form1 contains the dbgrid
  • in the menu menu when you click the option 'Open form with dbgrid' there i open query
  • in form1.Oncreate i set the parameters and it find record 5

testcae - dbgrid locate.zip

Link to comment
Share on other sites

First I tell you Thanks for your answers
Your example works ... but I haven't solved the problem😭
If you move Country: TMyQuery and dsCountry: TMyDataSource on Form1 ... the cursor after Locate stays on the first record.
Try and let me know.
if the Dataset and the Grid are on the same form .. the problem occurs.

You want to check

GRAZIE🙂

Link to comment
Share on other sites

That's right .. that doesn't work, but that has to do with the fact that loading the database and executing the code may be too fast.

In addition, it is never a good idea to put Queries and Datasets on the form, that's exactly what the DataModule are for.

I would choose a different setup. Try it with a DataModule then I think you don't have the problem anymore or like in my example.
When using DataModules all Querie and Dataset are everywhere available.


Having Query and datasets available on a form has no added value, it's the wrong approach for database development.

Regards Peter

Link to comment
Share on other sites

haha...of course you don't have to agree with that 😉

My largest application is about 200 forms, 20 data modules and not a single query or dataset on the form.
With a dataset you have everything neatly organized and you can address any query/dataset as long
as you integrate the DataModule in your form.

But also smaller applications are always developed with DataModules.

You have to choose the approach that suits you and your application

Link to comment
Share on other sites

Hi,

trying I have this sequence:

The database after locate is on the right record!

the first "NotifyAjax" from the unidbgrid .. lead to the right position.
.. I read the value 4 in Datasource.DataSet.RecNo

the next "NotifyAjax" .. 

in unit uniDBGrid;

procedure TUniCustomDBGrid.NotifyAjax; --> HookEvents(True); ---> HookFilter(true);

does so to modify the DataSet.OnFilterRecord

          FFilterHooked := True;
          FSaveFilter := Ds.OnFilterRecord;
          Ds.OnFilterRecord := H_OnFilterRecord;

... and Datasource.DataSet.RecNo returns to the value 0

if i impose this fix .. i don't have the problem.

//    HookFilter(ASet);
    HookFilter(False);  

Not using filters on the grid ...can I apply this correction?? .. What happen?

I know this is not the right solution ..
... but someone tells me if he has the same problem ..and if it has a solution.

Thank you and I await a reply

 

Link to comment
Share on other sites

On 9/2/2021 at 2:02 PM, gerardocrisci said:

I have a problem using MyDAC (10.4.4) with UNIGUI.
When using Locate before displaying the form, the record selected on the uniDBgrid is always the first, the cursor does not move.

 

Hello Gerardo,

I have Devart ibdac_7.4.4_d27std  (Last update). 

I Tested as the same protocol you did, with FireBird dataBase.

Result 

You are right, in your test case, i get the same behavior :   No row is detected after locate methode.

Discussion

it's not a good idea, to open the DataSet on DesignTime.

When you do it on a conventional opening, as usually we do (Opening the DataSet on Activate Form, or OnCreate Frame) the locate methode find the correct row.

 

Here is in attachment a testCase.

 Regards.

Locate.7z

Link to comment
Share on other sites

I found the problem

procedure TUniCustomDBGrid.HookFilter(ASet: Boolean);
...
begin
  if FDataLink <> nil then
    if (DataSource <> nil) and (DataSource.DataSet <> nil) then
    begin
      Ds := DataSource.DataSet;
      if ASet then
      begin
       ...
        if (...) then
        begin
         ...
          FSaveFilter := Ds.OnFilterRecord; 
          Ds.OnFilterRecord := H_OnFilterRecord; 
        end;
      end
....

the change of OnFilterRecord notified after locate returns the cursor to the first record..

Just start "HookFilter" before "Locate"
So it would be enough

   UniDBGrid1.HookFilter(True);
   MyQuery1.Locate('Country_ID', 5, []);

 but HookFilter is private and not directly accessible ..

So to start it just confirm the Datasource
 SetDataSource(Value: TDataSource); --->HookEvents(True); ---> HookFilter(True);

UniDBGrid1.DataSource := MyDataSource1;
MyQuery1.Locate('Country_ID', 5, []);

it is therefore easy to create an adjustment that functions any library to access the data.

😀😀😃

I am happy

Link to comment
Share on other sites

  • 5 months later...

Hi! I also faced this problem. Maybe it could be fixed on the component side? This is a very used case: store last grid selection/position, but with current component behavior have no any solution except of such private call with unpredictable consequences.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...