Autor Téma: FireDAC - Refresh  (Přečteno 757 krát)

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
FireDAC - Refresh
« kdy: 11-01-2017, 11:41:59 »
zdar,
narazil jsem na zvláštní (teda podle mě je zvláštní) chování FireDAC ve spojení s Firebirdem (ostatní db jsem nezkoušel, je možný, že se to tak chová všude).
Refresh se chová rozdílně, když je vyplněno UpdateOptions.KeyFields (nebo nevyplněno).
Mám připojený DBGrid a když v KeyFields není nic vyplněno a zavolám Refresh, tak se znovu načtou pouze záznamy, které grid zobrazuje.
Když KeyFields vyplním a zavolám refresh provede se Refresh, ale načtou se úplně všechny záznamy, jako by se zavolalo ještě FetchAll.
Funguje to tak i když nastavím u nějakého fieldu, že je klíč - ProviderFlags := [pfInKey]

Testováno na Berlin Upd2

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #1 kdy: 16-10-2017, 18:38:17 »
Tak jsem se na ten problém zeptal podpory, podle nich je to by-design, mě se to chování nezdá správné. Jak píšou, na řádku 5141 se ten FetchAll opravdu volá, když je vyplněný index.
Citace
The behaviour that you describe looks to be as designed. By setting pfInKey in the provider flags, you are telling FireDAC that the table in the query has a primary key. If I look at line 5141 of FireDAC.Comp.DataSet.pas,  I see that the rows will be fetched if a primary key is defined:

if sKeyFields <> '' then begin
   CheckFetchedAll;

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #2 kdy: 16-10-2017, 23:51:33 »
O jake komponente se tu bavime (TFDQuery)? Muzu poprosit o jeji uplnou konfiguraci?
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #3 kdy: 17-10-2017, 09:38:07 »
Jo jedná se o TFDQuery.  Když nastavím pfInKey:
Kód: [Vybrat]
FDQuery1.Fields.FieldByName('MY_ID').ProviderFlags := [pfInWhere, pfInUpdate, pfInKey]; nebo v update options nastav KeyFields.
Tak refresh začne dělat FetchAll.
Protože v FireDAC.Comp.DataSet.pas na řádku 5141 je:
Kód: [Vybrat]
if sKeyFields <> '' then begin
   CheckFetchedAll;

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #4 kdy: 08-11-2017, 05:26:30 »
Ano, tak tomu je. Metoda si zapamatuje hodnotu klice, vycisti storage, pak prenese vsechny zaznamy a snazi se lokalizovat zaznam s ulozenou hodnotou klice.

Myslim si tedy ze FireDAC jen nechce ztratit existujici pozici kurzoru a v ramci "jednoduchosti" prenese vsechny zaznamy. Se zmenou parametru muze totiz objekt prenest jiny resultset, predtim zamereny zaznam uz nemusi existovat, nebo muze byt na jine pozici. Lze tam i vycist, ze pokud neni v zaznamu klic (lRecIndSet == False), pak se nastavuje kurzor podle taktez ulozeneho RecNo.

Pokud tomu tak je, bylo by rozumnejsi kdyby se mu podarilo obnovit jen zaznam s kurzorem a prenesl packety do velikosti poloviny RowsetSize nahoru a dolu (pripadne patricnym pomerem nahoru a dolu). Co je nejspis problem je jak po uprave bindovanych parametru prikazu ziskat specificky packet zaznamu kde se nachazi ten s ulozenou hodnotou klice (ten puvodne zamereny). Zkusim se podivat na moznosti, byt tomu moc sanci nedavam...
« Poslední změna: 08-11-2017, 05:47:02 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #5 kdy: 08-11-2017, 06:10:07 »
Zkusim se podivat na moznosti, byt tomu moc sanci nedavam...

Chovanim metodu podobnou Resync s reflexi zmen hodnot bindovanych parametru.
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #6 kdy: 08-11-2017, 07:02:09 »
Zkusim se podivat na moznosti, byt tomu moc sanci nedavam...

A sance (alespon v soucasnosti) nejsou. FireDAC nedokaze prenest z DBMS specificky packet zaznamu obsahujici urcity zaznam (i kdyby to DBMS podporoval, takova implementace neexistuje). Je vsak zbytecnost pri fmOnDemand prenaset vsechny zaznamy jen pro zachovani zamereneho kurzoru. Porad by slo (treba i na zaklade nastaveni nejake nove property ve smyslu ForgetCursorAtRefresh) tahat packety zaznamu dokud se neobjevi ten puvodne zamereny, dotahnout packety do velikosti RowsetSize a smycku ukoncit nebo zamereni zapomenout a prenest jen RowsetSize pocet zaznamu.
« Poslední změna: 08-11-2017, 07:12:38 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #7 kdy: 08-11-2017, 08:51:44 »
Řešil jsem to s technickou podporou, výsledek 0, je to tak v kódu, tak to MUSÍ být dobře, o tom, že je to nesmysl odmítli diskutovat.
- nikde není popsáno v dokumentaci, že přidání primárního klíče mění způsob jakým se dělá refresh
- žádný jiný knihovny to nedělaj (co jsem zkoušel)
- když jsem ten Refresh přepsal a to CheckFetchedAll jsem vyhodil, tak všechno funguje, načte to pouze tolik záznamů aby to našlo předchozí pozici

V příloze je patch, kterej to opraví, funguje mi to v 10.2.

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #8 kdy: 08-11-2017, 09:10:13 »
- když jsem ten Refresh přepsal a to CheckFetchedAll jsem vyhodil, tak všechno funguje, načte to pouze tolik záznamů aby to našlo předchozí pozici

Tomu popravde neverim (muzu overit) :) Interni storage se vyprazdnuje (Table.Clear) a LocateRecord prave s tim storage pracuje (FSourceView.Search). Musi se do nej ale znova prenest zaznamy z DBMS. Jen namisto prenosu vsech si v pripade "on demand" rezimu vyrob smycku a tahej packety dokud nenajdes zaznam shodujici se s ulozenym klicem, pak ze smycky vyskoc. Nevim o moznosti kdy by to za tebe delal ten storage. Nicmene i tak se muze stat ze se prenese zbytecne moc zaznamu (posledne vybrany zaznam uz nemusi v obnovenem resultsetu existovat). A to vse jen za cenu pozice kurzoru.
« Poslední změna: 08-11-2017, 09:12:52 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2976
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:FireDAC - Refresh
« Odpověď #9 kdy: 08-11-2017, 09:41:35 »
Citace
nikde není popsáno v dokumentaci, že přidání primárního klíče mění způsob jakým se dělá refresh
Ja som na to narazil ;)
Citace
A to vse jen za cenu pozice kurzoru.
Ja ho beztak chcem mať na prvej/poslednej pozícii :)
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #10 kdy: 08-11-2017, 10:15:09 »
Tomu popravde neverim (muzu overit) :)
Já jsem nezkoumal kód, ale udělal jsem si demo s tabulkou, která má 10.000 záznamů zobrazených v gridu. Když jsem přesunul pozici v gridu na patřičný počet záznamů a dal refresh, tak se to chovalo dobře.
Když jsem udělal pozici na konec (načetlo se všechno) a potom jsem skočil někam doprostřed a udělal refresh, tak se načetlo jen tolik záznamů od začátku tabulky aby se našel záznam, který má pozici. Co bylo nad už se nenačetlo i když před refresh to načtené bylo.

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #11 kdy: 08-11-2017, 10:24:50 »
Ja ho beztak chcem mať na prvej/poslednej pozícii :)

Pro tvuj pripad je to vyhodne, protoze chces syejne vzdy tahat vsechny zaznamy :) I tak se ale bude FireDAC snazit nastavit kurzor tam kde byl. Problem je kdyz mas "on demand" rezim a provedes neco takoveho:

Kód: Delphi [Vybrat]
  1. FDQuery.SQL.Text := 'SELECT ID, MyField FROM MyTable WHERE MyField BETWEEN :LowValue AND :HighValue';
  2. FDQuery.ParamByName('LowValue').AsInteger := 1;
  3. FDQuery.ParamByName('HighValue').AsInteger := 10;
  4. FDQuery.Open;
  5.  
  6. FDQuery.ParamByName('LowValue').AsInteger := 11;
  7. FDQuery.ParamByName('HighValue').AsInteger := 500000;
  8. FDQuery.Refresh; // ← tady se prenesou vsechny zaznamy pri hledani posledne vybraneho (v resultsetu v tomto pripade nebude)

S vyse uvedenym refreshem si nelze poradit jinak nez prenest vsechny zaznamy (i kdyz to bude davkove). Nebo se na zachovani puvodni pozice kurzoru vykaslat. Proto bych byl pro novou volbu nastaveni. Pri jejim vypnuti by sis mohl zaznam sam lokalizovat (protoze vis jak jsi upravil bindovane parametry a tim padem mas sanci odhadnout zda muze drive vybrany zaznam existovat v nove prenasenem resultsetu).
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #12 kdy: 08-11-2017, 10:31:13 »
Když jsem udělal pozici na konec (načetlo se všechno) a potom jsem skočil někam doprostřed a udělal refresh, tak se načetlo jen tolik záznamů od začátku tabulky aby se našel záznam, který má pozici. Co bylo nad už se nenačetlo i když před refresh to načtené bylo.

To zni spis jakoby se o to nacteni dat postaral sam grid (resp. jeho skrolovani). Zkus zrusit propojeni s gridem a pote co zavolas svuj modifikovany refresh zkus overit kolik je zaznamu ve storage (tj. kolik zaznamu se po jeho vycisteni na klienta skutecne preneslo):

Kód: Delphi [Vybrat]
  1. FDQuery.Refresh;
  2. FDQuery.Table.Rows.Count; // ← tipuju 0
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #13 kdy: 08-11-2017, 10:49:47 »
Funguje to i bez připojenýho gridu.
Kód: [Vybrat]
  FDQuery1.Refresh;
  Memo1.Lines.Add(IntToStr(FDQuery1.RecordCount));
  Memo1.Lines.Add(IntToStr(FDQuery1.Table.Rows.Count));
  Memo1.Lines.Add(IntToStr(FDQuery1.RecNo));
Když stojím na prvním záznamu, výsledek je:
50
50
1
na posledním:
10001
10001
10001

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2976
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:FireDAC - Refresh
« Odpověď #14 kdy: 08-11-2017, 10:51:00 »
Citace
S vyse uvedenym refreshem si nelze poradit jinak nez prenest vsechny zaznamy (i kdyz to bude davkove). Nebo se na zachovani puvodni pozice kurzoru vykaslat.
Ja tú pôvodnú pozíciu naozaj nepotrebujem. Keď pracujem s tabuľkami (vo VST), tak používam Locate(). Pri SELECT
  • buď prechádzam celý dataset
  • alebo ho celý načítam do VST a zahadzujem ho (Close)
Citace
Proto bych byl pro novou volbu nastaveni. Pri jejim vypnuti by sis mohl zaznam sam lokalizovat
To si musím znova pozrieť čo má na čo vplyv.
Citace
(protoze vis jak jsi upravil bindovane parametry a tim padem mas sanci odhadnout zda muze drive vybrany zaznam existovat v nove prenasenem resultsetu).
Buď viem, že tam nebude, alebo nemám šancu to odhadnúť. Lebo to záleží na štruktúre údajov užívateľa.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #15 kdy: 08-11-2017, 11:27:01 »
Funguje to i bez připojenýho gridu.

A jo. Uz tomu chapu. Tys de-facto odrovnal cely blok hledani podle hodnoty klice. To muzes sundat rovnou cely ten blok (protoze efektivne nebude nic delat) a lokalizovat rovnou pomoci RecNo (cimz muzes kurzorem odskocit na jiny zaznam nez byl predtim vybrany):

Kód: Delphi [Vybrat]
  1.   lRecIndSet := False;
  2.   if sKeyFields <> '' then begin
  3.     CheckFetchedAll; // ← preskocenim prenosu radku nemuze LocateRecord nikdy vratit True (protoze je storage prazdny)
  4.     if LocateRecord(sKeyFields, vLastKeyValue, [], iNewRecNo) then begin
  5.       FRecordIndex := iNewRecNo;
  6.       lRecIndSet := True; // ← sem se nikdy nedostanes
  7.     end;
  8.   end;
  9.   if not lRecIndSet then // ← a tim padem se ti kurzor lokalizuje pomoci ulozeneho RecNo (prenos zaznamu je tady resen efektivneji)
  10.     InternalSetRecNo(iLastRecNo);
« Poslední změna: 08-11-2017, 11:54:15 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #16 kdy: 08-11-2017, 11:38:13 »
Ja tú pôvodnú pozíciu naozaj nepotrebujem. Keď pracujem s tabuľkami (vo VST), tak používam Locate().

Soucasna implementace FireDAC (Tokyo) se bude o lokalizaci snazit pokazde. Bud klicem (neefektivne prenosem vsech zaznamu) nebo RecNo (cimz muzes skoncit na jinem zaznamu nez byl predtim vybrany). Prave proto bych byl pro novou volbu nastaveni (neco jako ForgetCursorAtRefresh a rucni lokaci, pokud o ni mas zajem).
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2976
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:FireDAC - Refresh
« Odpověď #17 kdy: 08-11-2017, 13:10:03 »
Keďže to ušetrí prostriedky a čas, tak záujem mám. Tak ako aj o MVC ;)
Tá lokalizácia pomocou ID sa dá potlačiť nastavením nejakých vlastností. Len si nepamätám ktorých a ako. Tu je k tomu nejaký pokec http://docs.embarcadero.com/products/rad_studio/firedac/frames.html To je základná strana. Viď prílohu.
« Poslední změna: 08-11-2017, 13:12:57 od Stanislav Hruška »
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #18 kdy: 08-11-2017, 15:10:50 »
Keďže to ušetrí prostriedky a čas, tak záujem mám.

Ja to myslel jen jako navrh nove property nastaveni pro report do Embarcadera. Jinak ta samotna lokalizace zaznamu (LocateRecord) bude rychla protoze se prohledava uz jen interni storage. Co zabere cas je prenos zaznamu z DBMS prave do te storage. A to je vlastne to co tady resime.

Rezim prenosu (FetchOptions.Mode) se momentalne pri volani Refresh ignoruje. Pri fmOnDemand se tak namisto hledani klice puvodne vybraneho zaznamu postupnym prenasenim packetu dokud neni zaznam nalezen natvrdo prenasi vsechny zaznamy (jakoby byl nastaven rezim fmAll). A pri rezimu fmAll, pokud se predchozi zaznam "hleda" pomoci indexu radku RecNo (protoze v datasetu neni klic) se zaznamy ziskavaji postupnym prenosem packetu dokud jich neni dostatek (jakoby byl nastaven rezim fmOnDemand).

No a pak jeste chybi nejake "vypnuti" te lokalizace posledne vybraneho zaznamu pri volani Refresh pro stav, kdy mas rezim fmOnDemand a vis ze po uprave parametru dotazu nemuze posledne vybrany zaznam v resultsetu existovat (nebo kdy neresis posledni pozici kurzoru). Aby se dalo hledani zcela vyhnout.

Tá lokalizácia pomocou ID sa dá potlačiť nastavením nejakých vlastností.

Ne v tomto pripade, tj. volani metody Refresh, implementace Delphi Tokyo.
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1765
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:FireDAC - Refresh
« Odpověď #19 kdy: 09-11-2017, 08:56:14 »
S vyse uvedenym refreshem si nelze poradit jinak nez prenest vsechny zaznamy (i kdyz to bude davkove). Nebo se na zachovani puvodni pozice kurzoru vykaslat. Proto bych byl pro novou volbu nastaveni. Pri jejim vypnuti by sis mohl zaznam sam lokalizovat (protoze vis jak jsi upravil bindovane parametry a tim padem mas sanci odhadnout zda muze drive vybrany zaznam existovat v nove prenasenem resultsetu).

Já jsem u nás refresh vyřešil tak, že dám do DB dotaz, který mi vrátí jen množinu jen změněných záznamů (podle primárního klíče), z otevřené původní Firedac query ty řádky na úrovni DataSet.Table (což je interní storage ve které má firedac načtené data) odstraní, a nově získané tam přidá. Funguje to léta perfektně.

z pohledu následníka firedac query
Kód: [Vybrat]
procedure TXDataSet.gRefreshRows( sSQL:string; const sKeys: string; iId: Integer);
var
  adsRefresh: TAdQuery;
  s: string;
  iOrder: Integer;
  opt: TADDataSetLocateOptions;
  bmk: TBookmark;
  oDestRow:TADDatSRow;
  iRowIndex: Integer;
begin
  adsRefresh := TAdQuery.Create(nil);
  adsRefresh.Database := Self.Database;
  try
    // remove ORDER BY protoze subselekty to nesmi obsahovat
    s := LowerCase(sSQL);
    iOrder := Pos('order by', s);
    if iOrder > 0 then
      sSQL := Copy(sSQL, 1, iOrder - 1);

    // wrapni SQL
    sSQL := Format('SELECT T_Refresh.* FROM (%s) T_Refresh WHERE T_Refresh.%s = %d', [sSQL, sKeys, iId]);

//    MsgOk(sSQL);
    adsRefresh.SQL.Text := sSQL;
    adsRefresh.Open;
    DisableControls;
    iRowIndex:= -1;
    bmk := GetBookmark;
    try
      opt := []; // hledej od zacatku a odstran vsechny zaznamy z lokalnich dat
      while LocateEx(sKeys, iId, opt) do
      begin
        BeginBatch(True);
        try
          oDestRow := GetRow;
          if oDestRow <> nil then
          begin
            iRowIndex := oDestRow.Index;
            oDestRow.Delete();
            Table.Rows.Remove(oDestRow);
          end;
        finally
          EndBatch;
        end;
      end;

      // append refreshed records or not, if doesn't exist

      while not adsRefresh.Eof do
      begin
        if iRowIndex >= Table.Rows.Count then
          iRowIndex := -1;
        CopyOneRow(adsRefresh, [coRefresh, coAppend], iRowIndex);
        adsRefresh.Next;
      end;
    finally
      adsRefresh.Close;
      if BookmarkValid(bmk) then
        GotoBookmark(bmk);
      EnableControls;
    end;
  finally
    adsRefresh.Free;
    FreeBookmark(bmk);
  end;

a klíčová low level CopyOneRow, převzato z FireDac zdrojáků a upraveno

Kód: [Vybrat]

procedure TXDataSet.CopyOneRow(ASource: TDataset; AOptions: TADCopyDataSetOptions; iPos: Integer);
var

  eStatus: TUpdateStatus;
  oSrcRow, oDestRow: TADDatSRow;
  aMap: TADArrayOfInteger;
begin
  if (ASource = nil) or (ASource = Self) then
    Exit;

  StartWait;
  try
    // Run batch update.
    BeginBatch;
    try
      if coAppend in AOptions then
        eStatus := usInserted
      else
        eStatus := usModified;

      // Copy data
      if eStatus in [usInserted, usModified] then

        // Merge data into main table. Do not produce row version.
        if coRefresh in AOptions then begin
          if eStatus = usInserted then
          begin
            oDestRow := Table.NewRow(False);
            if iPos = -1 then
              Table.Rows.Add(oDestRow)
            else
              TADDatSTableRowList(Table.Rows).AddAt(oDestRow, iPos);
          end
          else
            oDestRow := GetRow();
          oSrcRow := TADDataSet(ASource).GetRow();
          if Length(aMap) = 0 then
            Table.MakeColumnMap(oSrcRow, aMap);
          Table.Import(oSrcRow, oDestRow, aMap);
          oDestRow.AcceptChanges();
        end
    finally
      EndBatch;
    end;
  finally
    StopWait;
  end;
end;



Embarcadero MVP - Czech republic

Offline chaloup

  • Mladík
  • **
  • Příspěvků: 85
  • Karma: 9
    • Verze Delphi: Delphi 10.2
Re:FireDAC - Refresh
« Odpověď #20 kdy: 09-11-2017, 09:18:07 »
Já jsem u nás refresh vyřešil tak, že dám do DB dotaz, který mi vrátí jen množinu jen změněných záznamů (podle primárního klíče), z otevřené původní Firedac query ty řádky na úrovni DataSet.Table (což je interní storage ve které má firedac načtené data) odstraní, a nově získané tam přidá. Funguje to léta perfektně.
Jak se řeší změny/přidané záznamy ostatních uživatelů? Co je T_Refresh?

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1765
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:FireDAC - Refresh
« Odpověď #21 kdy: 09-11-2017, 09:28:17 »
Já jsem u nás refresh vyřešil tak, že dám do DB dotaz, který mi vrátí jen množinu jen změněných záznamů (podle primárního klíče), z otevřené původní Firedac query ty řádky na úrovni DataSet.Table (což je interní storage ve které má firedac načtené data) odstraní, a nově získané tam přidá. Funguje to léta perfektně.
Jak se řeší změny/přidané záznamy ostatních uživatelů? Co je T_Refresh?

Kód: [Vybrat]
SELECT T_Refresh.* FROM (%s) T_Refresh

Vezme se originální query, to se obalí a dá se mu alias.

Ostatní záznamy, uživatel nevidí dokud si nedá manuální refresh nebo to nevynutím (což je stejná situace jako když jen sedíš u PC a nic neděláš, taky neuvidíš cizí). Tohle se používá při editaci jednoho záznamu. Samozřejmě se dá ta T_Refresh napsat aby vrátila i nové nebo změněné záznamy, pokud je dokážeš poznat. Ono ale většinou zákazníka moc nezajímají cizí záznamy a při různých kolizích to stejnak musíš otestovat v ten okamžik.



Embarcadero MVP - Czech republic

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 376
  • Karma: 16
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
    • Ibi Yoyo :)
Re:FireDAC - Refresh
« Odpověď #22 kdy: 09-11-2017, 20:35:52 »
Tohle se používá při editaci jednoho záznamu.

Nevim zda to chapu spravne, ale k obcerstveni jednoho zaznamu existuje metoda RefreshRecord. Jinak nejvyssi efektivitu ziskas vlastnorucne psanym strankovanim. V SQL pomoci LIMIT a OFFSET pripadne rozsahem klicu (s dotazenim vice zaznamu v pripade absence zaznamu v okne).
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1765
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:FireDAC - Refresh
« Odpověď #23 kdy: 09-11-2017, 23:21:58 »
Nevim zda to chapu spravne, ale k obcerstveni jednoho zaznamu existuje metoda RefreshRecord.

Byl tam nejaky problem u slozenych dotazu s vice join
Embarcadero MVP - Czech republic

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Křestní jméno zpěváka Gotta: