Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Konzept SQL-Anwendung (https://www.delphipraxis.net/102318-konzept-sql-anwendung.html)

stahli 26. Okt 2007 16:00

Datenbank: FB • Version: 2 emb. • Zugriff über: IBX

Konzept SQL-Anwendung
 
Hallo zusammen,

ich arbeite an einer SQL-Anwendung und will Euch mal fragen, ob das überhaupt die richtige Herangehensweise ist...

Ich nutze FB2 embeded mit einigen Tabellen und verschiedenen DB-Komponenten. Hier z.B. auch eine eigene DBPanel, die DB-Inhalte formatiert anzeigt und u.a. vom Nutzer per Drag&Drop verschoben werden kann.

Der Nutzer soll letztlich nicht merken, dass da eine Datenbank im Hintergrund steckt. Er soll sich also nicht mit Tabellen, DataSet-Status etc. herumschlagen müssen...

Es gibt eine Edit-Komponente, mit der der Nutzer Feldinhalte ändern kann, die bei jedem Tastendruck sofort in der Datenbank aktualisiert werden und überall "gleichzeitig" aktualisiert angezeigt werden.
Das ist also ähnlich den Eigenschaften im Objektinspektor (Weiss jemand eigentlich wie das in der IDE realisiert ist, mit CDS?).

Dann gibt es in dem DataModule einige Funktionen, die Berechnungen und Änderungen in der Datenbank vornehmen. Anschließend werden die betroffenen Datenmengen geschlossen, wieder geöffnet und an die alte Stelle positioniert:

Delphi-Quellcode:
procedure TDataModuleSatzUndSieg.DauerDisziplingruppenBerechnen(DBSqlWhere:TDBSqlWhere);
var IBSQL1,IBSQL2:TIBSQL;
    Disziplingruppe,C,SDG,SDI,BDG,BDI:Integer;
begin
  IBSQL1:=TIBSQL.Create(nil);
  IBSQL1.DataBase:=IBDatabaseSatzUndSieg;
  IBSQL2:=TIBSQL.Create(nil);
  IBSQL2.DataBase:=IBDatabaseSatzUndSieg;
  with IBSQL1 do begin
    Close;
    SQL.Clear;
    SQL.Add('select * from T_Disziplingruppen');
    SQL.Add('order by Id');
    ExecQuery;
    while (not Eof) do begin
      Disziplingruppe:=FieldByName('Id').AsInteger;
      with IBSQL2 do begin
        Close;
        SQL.Clear;
        SQL.Add('select Count(*) as C from T_Disziplinen');
        SQL.Add('where (Disziplingruppe=:Disziplingruppe)');
        ParamByName('Disziplingruppe').AsInteger:=Disziplingruppe;
        ExecQuery;
        C:=FieldByName('C').AsInteger;
        Close;
      end;
      with IBSQL2 do begin
        Close;
        SQL.Clear;
        SQL.Add('select Sum(DauerGeplant) as BDG, Sum(DauerIst) as BDI from T_Disziplinen');
        SQL.Add('where (Disziplingruppe=:Disziplingruppe)');
        ParamByName('Disziplingruppe').AsInteger:=Disziplingruppe;
        ExecQuery;
        BDG:=FieldByName('BDG').AsInteger;
        BDI:=FieldByName('BDI').AsInteger;
        Close;
      end;
      ...
      Next;
    end;
  end;
  IBSQL1.Free;
  IBSQL2.Free;
  RefreshDataSet(IBTableDisziplingruppen);
end;

procedure RefreshDataSet(DataSet:TDataSet;IdField:String='';IdValue:String='');
var TmpBookmark:TBookmark;
begin
  if (DataSet<>DataSetBlocked) then begin
    with DataSet do begin
      TmpBookmark:=nil;
      try
        TmpBookmark:=GetBookmark;
        DisableControls;
        Close;
        Open;
        ...
        if (not IsEmpty) then begin
          GotoBookmark(TmpBookmark);
        end;
      finally
        EnableControls;
        FreeBookmark(TmpBookmark);
        ...
      end;
    end;
    if ((IdField<>'') and (IdValue<>'')) then begin
      LocateDataSet(DataSet,IdField,IdValue);
    end;
  end;
end;
Hier liegt es letztlich bei mir, wann ich die DataSets aktualisiere und damit die erneute Anzeige der Datenbankinhalte veranlasse.
Das temporäre Erzeugen und Verschachteln von zwei IBSQL funktioniert, aber ...

... macht man das so, oder ist der Ansatz eher suboptimal?
(Abgesehen mal vom Einsatz von SP, die ich lieber erst mal außen vor lasse.)

stahli

mschaefer 26. Okt 2007 18:06

Re: Konzept SQL-Anwendung
 
Ja und Nein, also Du definierst ja dass der Anwender die Datenbankfunktionalität nicht merken soll, insofern ist das automatische "Aktualisieren" eine Vorgabe von Dir. Allerdings bringt ein Close oder Post auch eine deutliche Verzögerung mit sich und ich würde eine abgewandelte Strategie anpeilen:

1. Du kannst über das Form Event OnKeyPress auf alle Tastendrücke des Formulars reagieren. Hier würde ich einen Timer disabeln und anschliessend wieder Enablen, der für das Recordupdaten zuständig ist. Also nicht nach jedem Tastendruck, sondern nach einer Zeit ohne Tastendruck aktualisieren.

2. Im OnTimner Event würde ich keinen harten Post nehmen, sondern ein 'UpdateRecord', dann wird zunächst nur der interne Dataset aktualisiert, dass geht schnell. Nun gibt es zwei Post Strategien: Man kann einen zweiten Timer für das Hard-Post mit einer längeren Zeit nehmen und in dessen OnTimerEvent das Post setzen (=Close und dann Open) und man muß beim Schliessen des Formulars noch ein Post schicken wenn der DataSet noch im Edit oder Insert-Mode ist.

Dass wären meine Vorschläge // Martin

stahli 26. Okt 2007 18:46

Re: Konzept SQL-Anwendung
 
Hallo Martin,

danke für die Info. Ein Zeitproblem habe ich eigentlich nicht.

Die Änderungen in der DB realisiere ich durch dynamische SQL-Statements.
-> update Table set Field=Text where IDField=AktuelleId

Das machen die Datenbankkomponenten selbständig entsprechend der angebundenen Datenmenge und den in den Eigenschaften zugeordneten Feldnamen.
Dann schließen und öffnen sie die angebundene Datenmenge mit der o.g. Prozedur
-> RefreshDataSet

Das geht eigentlich schnell genug. Ein Post ist insofern nicht notwendig.

Die Datenbankkomponenten, die Datenmengen darstellen (und entsprechend etwas Zeit dafür brauchen) können auf Wunsch vom sofortigen Zeichnen ausgeschlossen werden und werden dann erst neu gezeichnet, wenn Zeit dafür ist. Dafür werden sie anstatt sie sofort zu zeichnen in eine Warteliste aufgenommen. Ein Timer arbeitet die Liste dann ab, bis sie wieder leer ist.

Also wenn mein Quellauszug oben nicht völlig falsch ist, hilft mir das schon weiter. :-)

Danke von Stahli

mschaefer 26. Okt 2007 19:44

Re: Konzept SQL-Anwendung
 
Naja dass ist ist er sicher nicht!

Das EnableControls würde ich noch nach dem Locate setzten, aber funktionieren tut es.
Jedenfalls würde ich bei einer lokalen Datenbank kein wirkliches Problem sehen.

Grüße // Martin


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:42 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz