![]() |
AW: Die Sache mit dem Listenproperty
Hi Sakura
Genaugenommen wird die Anfrage bei jedem lesezugriff auf das Property ausgeführt. Die Alternative wäre, die SQL-Anfrage ausserhalb des Datenmoduls dann da ausführen, wo ich sie brauche. Zum Bleistift in einem PageControl zur Anzeige von Metadaten auf der Mainform. Damit hätte ich dann eine weitere Prozedur in der Mainform, die es allenfalls zu ändern (und erstmal zu finden) gibt. Und wenn ich mehrere Informationen, für deren Beschaffung das Datenmodul zuständig ist, von ausserhalb abfrage, habe ich auch ausserhalb eine entsprechende Anzahl Methoden, die mir diese Infos beschaffen - und sollte sich irgendwas ändern, zum Bleistift an der Datenbank/Tabellenstruktur, darf ich alll diese Methoden ausserhalb des Datenmoduls da ändern, wo ich sie angelegt habe. Das muss nicht zwingend die Mainform sein, das kann eine andere Form oder ein Frame - im schlimmsten Fall pro Prozedure/SQL-Statement - sein. Wenn ich das im alles im Datenmodul habe, muss ichs auch nur da ändern. Auch wenn ich Methoden von ausserhalb nur aufrufe - wenn sich die Art des Aufrufens ändert (Parameter können sich ändern etc), darf ich alle diese Aufrufe an verschiedenen Stellen des Programmes ändern.
Delphi-Quellcode:
Eine gute Richtlinie ist es aber immer so zu entwickeln, als könnten solche Informationen an mehreren Stellen gleichzeitig gebraucht werden, das macht spätere Erweiterungen leichter. Auch bei Desktopanwendungen ist Multi-Threading schon lange keine Ausnahme mehr.
Ja eben: genau deswegen ist es besser, das Datenmodul stellt die Infos als Propery bereit. Ansonsten müsste jede dieser Stellen das SQL-Statement aufrufen. Das Statement selbst, bzw. desse Ausführung, dürfte vo der Performance her kaum ins Gewicht fallen. Und nochmals: sollte ich mit einem andern als dem Hauptthread auf das Property zugreifen, dann nur in einer Criticalsection. Anders sieht es allerdings aus, wenn ich meine BilderDatenbank abfrage: Hier werden die Ergebnisse pro Datensatz in eine Klasse geschrieben (und diese in eine Objectliste gepackt), so dass die Abfrage selbst im Normalfall nur einmal durchgeführt werden muss. Gruss Delbor |
AW: Die Sache mit dem Listenproperty
Hi,
leider hast du offenbar überhaupt nicht verstanden, was ich geschrieben habe. Zitat:
Zitat:
Zitat:
Zitat:
Warum lädst Du mit jeder Anfrage sich nicht ändernde Daten neu? Das ist grundsätzlich kein gutes Vorgehen. Selbst wenn es schnell geht, macht es schnell einen spürbaren Unterschied in der Geschwindigkeit, je nachdem, wie oft das gemacht wird. :gruebel: ...:cat:... |
AW: Die Sache mit dem Listenproperty
Hi Sakura
Ich hab mir DeddyHs Atwort zuunterst auf Seite eins nochmal angesehen. Meinst du die? Das könnte dann etwa so umgesetzt werden:
Delphi-Quellcode:
Stimmt, so wird die Abfrage nur einmal durchgeführt, vorausgesetzt die Tabelle ändert sich nicht. Was sie allerdings zumindest zur Laufzeit nie tun sollte.
function TFDMySQLDml.GetContentmasterTables: TStringlist;
var SqlString : String; I: integer; begin if FContentmastertables = Nil then then begin FContentmastertables := Tstringlist.Create; SqlString := 'SHOW TABLES'; FDQueryMain.Open(SqlString); FDQueryMain.First; while not FDQueryMain.Eof do begin FContentmastertables.Add(FDQueryMain.Fields.Fields[0].AsString); FDQueryMain.Next; end; FDQueryMain.Close; end; Result := (FContentmastertables); end; Gruss Delbor PS: Oder meinst du etwa dies aus Beitrag 18: Zitat:
Hier greift das Datenmudul nach oben*, was bei einer Trennung der Programmlogiken in verschiedene Schichten eben vermieden werden soll. *Zumindest, wenn ich den Aufruf richtig interpretiere. |
AW: Die Sache mit dem Listenproperty
Kombinier doch einfach alles:
Delphi-Quellcode:
type
TDingens = class private FTablenames: TStringList; function GetInternalTablenames: TStringList; function GetTablenames(Index: integer): string; function GetTablenameCount: integer; property InternalTablenames: TStringList read GetInternalTablenames; public destructor Destroy; override; property TablenameCount: integer read GetTablenameCount; property Tablenames[Index: integer]: string read GetTablenames; end; ... destructor TDingens.Destroy; begin FTablenames.Free; inherited; end; function TDingens.GetInternalTablenames: TStringList; begin if not Assigned(FTablenames) then begin FTablenames := TStringList.Create; (* Hier jetzt der Code zum Befüllen *) end; Result := FTablenames; end; function TDingens.GetTablenames(Index: integer): string; begin //Hier wird auf die interne Property zugegriffen Result := InternalTablenames[Index]; end; function GetTablenameCount: integer; begin //Hier auch Result := InternalTablenames.Count; end; |
AW: Die Sache mit dem Listenproperty
Hi DeddyH
Hier habe ich zumindest unter FireDac ein Problem. In einer definierten Verbindung kann ich genau eine Datenbank angeben - zumindest muss ich das so interpretieren, nachdem Embarcadero in allen Definitionsbeispielen immer genau eine Datenbank angibt und dabei nichts von einer Verbindung zu mehreren Datenbanken dazuschreibt. Einzig Verbindungspooling bleibt da möglich zu sein. Aber wie ich das bis jetzt verstanden habe, ist ein Pool eine Menge verschiedener Verbindungen, und ich denke, so würde dies auch der Server interpretieren. Und das führt dann dazu, dass jede Verbindung in diesem Pool aus Sicht des Servers ihre eigenen Sessionvariablen hat. Als Beispiel die Veränderung des Wertes FMaxAllowedPacket. Die entsprechende Tabelle zeige ich mir so an:
Delphi-Quellcode:
Den Wert kann ich dann so ändern:
'SELECT Variable_Value FROM performance_schema.SESSION_VARIABLES WHERE VARIABLE_NAME = ''MAX_ALLOWED_PACKET''';
Delphi-Quellcode:
FDQueryMain.SQL.Text := 'SET @@global.Max_ALLOWED_PACKET = '+ IntToStr(Variable_Value);
Das akzeptiert der Server, weil es sich dabei um den Wert handelt, der für meine Verbindung gilt. Zumindest interpretie ich das so, da ich keine Rückmeldung wegen fehlender Rechte erhalte. Ob das wirklich tut, was es soll, kann ich erst kontrollieren, wenn das Programm mal ohne AV startet. Unter DBExpress hats funktioniert... Führe ich nun aber ein einfaches 'Show Tables' aus, erhalte ich in jedem Fall die Tabellennamen der DB, mit der ich aktuell Verbunden bin. Das heisst aber, dass ich unter der aktuellen Verbindung nur lesend und mit einem SELECT-Statement auf die Serverdatenbank und deren Tabellen zugreifen kann. Die Tabellennamen in in der DB performance_schema erhalte ich so nicht. Aber nachdem ich mir deinen Code nochmal angeschaut habe: Ich bin offensichtlich noch nicht ganz wach. Dein Code zielt eigentlich auf das DRY-Prinzip ab. Mit meinem kurz davor geposteten Quelltext müsste ich die Passagen zur Erstellung der Liste jedesmal wiederholen. Trotzdem lasse ich die ersten 3 Abschnitte jetzt mal stehen; vielleicht hat ja jemand eine Lösung, wie das Problem behoben werden könnte. Auf jeden Fall mal vielen Dank für deinen Code! Gruss Delbor |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz