Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Anleitung zum Umgang mit Datenbank Komponenten (https://www.delphipraxis.net/170860-anleitung-zum-umgang-mit-datenbank-komponenten.html)

Ykcim 6. Okt 2012 18:27

Datenbank: MySQL • Version: 5 • Zugriff über: Devart

Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo Zusammen,

ich habe bislang immer nativ auf die Datenbank zugegriffenund möchte aber in Zukunft mit Komponenten arbeiten. Zu diesem Zweck habe ich mir die Trial Komponente von Devart heruntergeladen.

Aber ich habe keine Erfahrung, wie ich mit diesen Komponenten arbeiten muss. Ich habe es zwar geschafft, dass in einem DBGrid die Daten aus einer sehr einfachen Abfrage (select * from Tabelle) angezeigt werden, aber damit endet auch schon meine Erfolgsstory.

Ich bin auf der Suche nach einer Anleitung / Leitfaden, wie ich in einer gut entwickelten Software die Kommunikation mit der Datenbank abwickle, wie ich selects, inserts, updates usw. vornehme und wie ich auch an die Daten selber rankomme, bevor sie ausgegeben werden - bislang habe ich sie mir immer in ein Array of Array of String eingeladen und konnte sie dort bearbeiten.

Ich habe zwar jetzt Objekte wie DataSet, DataSource, MyTable usw. verwendet, damit ich die Daten in dem Grid angezeigt bekomme, aber ich habe eigentlich keine Ahnung, was diese Objekte machen...

Ich brauche also auch etwas für Basics.

Wäre toll, wenn ich von Euch einige Tips bekommen könnte.

Vielen Dank

Ykcim

haentschman 6. Okt 2012 18:33

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo...

schau mal hier http://www.delphi-treff.de/tutorials/datenbanken/
... vieleicht gibt es da Teile die du noch nicht kennst. :zwinker:

Sir Rufo 6. Okt 2012 19:46

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Also bevor du dich daran machst, solltest du den Daten-Zugriff komplett einmal mit einer (oder auch mehrerer) Klasse(n) kapseln.
Dann im Code alle Zugriffe durch diese Klasse(n) führen.

Wenn das dann läuft, dann ziehst du dir davon eine abstrakte Klasse(n) und leitest die vorher erstellten davon ab.

Jetzt kannst du dir neue Klassen davon ableiten, nur das hier der Zugriff über die DevArt Komponenten läuft ;)

Hier mal ein kleines Beispiel für einen Ansatz:
Delphi-Quellcode:
// Abstrakte Klasse
TMySQLAbstract = class
public
  procedure Connect; virtual; abstract;
  procedure ExecQuery( AQuery : AnsiString; ACols : TCols; ARows : TRows ); virtual; abstract;
  procedure DisConnect; virtual; abstract;
end;

// konkrete MySQL-Native-Klasse
TMySQLNativeStore = class( TMySQLAbstract )
private
  FDB : TDB; // ???
public
  procedure Connect; override;
  procedure ExecQuery( AQuery : AnsiString; ACols : TCols; ARows : TRows ); override;
  procedure DisConnect; override;
end;

...
implementation

uses
  mysql_native_unit;

TMySQLNativeStore.Connect;
begin
  Connect;
end;

TMySQLNativeStore.ExecQuery;
begin
  ExecQuery( FDB, AQuery, ACols, ARows );
end;

TMySQLNativeStore.Disconnect;
begin
  Disconnect;
end;
BTW: Es ist nicht schlimm, wenn du nach der Umstellung diese Zwischenschicht weiterleben lässt.
Stell dir vor, die DevArt-Komponenten zicken rum oder gibt es für die Platform xy nicht ... dafür aber wieder ganz andere ... ei jo, einfach eine neue konkrete Ableitung und der Drops ist gelutscht ;)

DonManfred 7. Okt 2012 06:57

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Wir haben uns in der Firma vor einem Monat die Devart-Komponente MyDAC gekauft und ich muss sagen das war der beste Einkauf den wir je getätigt haben. Bis dahin hatten wir (bzw. ich als Programmierer) die ADO-Komponenten zum Zugriff zu MySQL benutzt; über ODBC.

Der Geschwindigkeitszugewinn den wir durch die MyDAC erfahren haben war bzw. ist ENORM. Ich kann die Komponenten von Devart wärmstens empfehlen.

Ich programmiere seit 5 Jahren nun intensiv mit Delphi. Vorher knappe 10 Jahre mit php und war es von da gewohnt meine SQLs immer manuell auszuführen bzw die Daten dann auch manuell abzufragen bzw zu verwenden.

TDBGrid ist ne nette Komponente wenn man es schnell umgesetzt haben will. ABER sie ist halt nicht sehr komfortabel.
Für einfach Liste wie "Anreden", "Geschlechter" usw nutzen wir sie auch. Aber sobald wir mehr komfort brauchen benutze ich die TAdvStringGrid-Komponente von TMS-Software die ich dann selber befülle und mit Checkboxen usw ausstatte.

Für "Basics" nutze ich idR zwei TMyQuery-Komponenten. Einmal als Abfrage-Query, eine weite für Inserts bzw Updates.

Vom Prinzip her läuft das dann meistens wie folgt ab:

Delphi-Quellcode:
qryorder.Active := false;
qryorder.SQL.Clear;
qryorder.SQL.Add('SELECT *, concat(ma.kd_vorname," ",ma.kd_nachname) AS dest, ma.kd_ma_google_email AS google_email, ma.kd_ma_google_passwort AS google_passwort , kd.*, bvh.* FROM beka_pp pp ');
qryorder.SQL.Add('LEFT JOIN beka_pptypen ppt ON pp_typID=ppt.ppt_id ');
qryorder.SQL.Add('LEFT JOIN beka_kunden ma ON pp_maID=ma.kd_id ');
qryorder.SQL.Add('LEFT JOIN beka_kunden kd ON pp_kdID=kd.kd_id ');
qryorder.SQL.Add('LEFT JOIN beka_bvh bvh ON pp_bvhID=bvh.bvh_id ');
qryorder.SQL.Add('LEFT JOIN beka_order o ON pp_belegID=o.order_beleg ');
qryorder.SQL.Add('WHERE pp_transfer=1 AND pp_datum_sort > "20120101" ORDER BY pp_maID ASC, pp_datum_sort DESC;');
qryorder.ExecSQL;
qryorder.Active := true;
if qryorder.RecordCount > 0 then begin
  while not qryorder.Eof do begin
    aktmaID := qryorder.FieldByName('pp_maID').AsInteger;
    [..]
    writeqry.SQL.Clear;
    writeqry.SQL.Add('UPDATE blablabla);
    writeqry.ExecSQL;
    qryorder.Next;
  end;
end;
qryorder und writeqry sind vom Typ TMyQuery und sind natürlich mit einer TMyConnection verbunden.

TMyDatasource brauche ich nur, wenn ich ein TDbGrid benutzen will. Solche Konstrukte gibt es zu hunderten in unserer Warenwirtschaft...

Ykcim 8. Okt 2012 11:45

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo Zusammen,

vielen Dank für Eure guten ANtworten. Ich habe mich intensiv damit beschäftigt und wollte hier einen kurzen Zwischenstand geben:

Ich habe eine ExecQuery Procedure geschrieben, mit der ich die Daten in ein Array of String einlese - dass ist die Ausgangsform, wie ich in der Vergangenheit die Daten dann weiterverarbeitet habe:

Delphi-Quellcode:
procedure ExecQuery2 (query: TMyQuery; var Cols: TCols; var Rows: TRows);
var I, J: integer;
begin
  SetLength(Cols,query.FieldCount);
  SetLength(Rows,query.FieldCount, query.RecordCount);
  for J:=0 to query.FieldCount -1 do
    begin
      Cols[J]:=query.Fields.Fields[J].FieldName;
    end;
  for I:=0 to query.RecordCount -1 do
    begin
      for J:=0 to query.FieldCount -1 do
        begin
          Rows[J,I]:=query.Fields.Fields[J].Text;
        end;
      query.Next;
    end;
end;

Mein Aufruf habe ich mit Eurer Hilfe dann so gestaltet (Er macht wenig Sinn, ich wollte nur mal üben...):

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Cols: TCols;
    Rows: TRows;
begin
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('select * from Benutzer where Vorname='+#39+Edit1.Text+#39);
  connect2;
  ExecQuery2(Form1.MyQuery1, Cols, Rows);
  FillGrid(StringGrid1, Cols, Rows);
  Disconnect2;
  showmessage('Stop');
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('update benutzer set Vorname='+#39+Edit2.Text+#39+' where Vorname='+#39+Edit1.Text+#39);
  MyQuery1.Execute;
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('select * from Benutzer');
  connect2;
  ExecQuery2(Form1.MyQuery1, Cols, Rows);
  FillGrid(StringGrid1, Cols, Rows);
  Disconnect2;
end;

So sehen meine Connect und disconnect proceduren aus.

Delphi-Quellcode:
procedure connect (Connection: TMyConnection);
var Datei: TextFile;
    MyString: String;
begin
  AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
  Reset(Datei);
  try
    ReadLn(Datei, MyString);
    Connection.Server := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    Connection.Username := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    Connection.Password := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    Connection.Database := copy(MyString, pos(':', MyString)+1, length(MyString));
  finally
    CloseFile(Datei);
  end;
  Connection.Connected:=true;
end;

Delphi-Quellcode:
procedure disconnect (Connection: TMyConnection);
begin
  Connection.Connected:=false;
end;
Wie gestaltet Ihr es, wenn Ihr die Zugangsdaten in einer Datei verwalten wollt? Meine SQL.SET kann jedes Textprogramm öffnen, was ja nicht so gedacht ist...


Zum Thema Klassen - habe ich noch keine Erfahrungen gesammelt, da ich noch nie eine gebaut habe...
Wozu macht die Klasse Sinn?
Warum macht die abstrakte Klasse Sinn, bzw wie werden die Proceduren abstrakt erstellt?

Ist das hier eine Zuweisung der Procedure ExecQuery aus der abstrakten Klasse zu der Procedure ExecQuery aus der konkreten Klasse?
Delphi-Quellcode:
TMySQLNativeStore.ExecQuery;
begin
   ExecQuery( FDB, AQuery, ACols, ARows );
end;

Vielen Dank für Eure Unterstützung

Ykcim

DonManfred 9. Okt 2012 06:21

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
anstelle von

Delphi-Quellcode:
+#39+Edit1.Text+#39
könntest Du auch

Delphi-Quellcode:
+QuotedStr(Edit1.Text)
verwenden. So hast Du dann immer einen String der Escaped ist. Also Eingaben wie 'Joe's Auto' würde sich auch wegschreiben lassen...

Beim auslesen wird Dir dann der DeEscaped String zurückgegeben...

DeddyH 9. Okt 2012 07:02

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Da aber sowieso DevArt verwendet wird, würde ich SQL-Parameter vorziehen, die werden mit ziemlicher Sicherheit unterstützt.

RWarnecke 9. Okt 2012 07:09

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Zitat:

Zitat von DeddyH (Beitrag 1186309)
Da aber sowieso DevArt verwendet wird, würde ich SQL-Parameter vorziehen, die werden mit ziemlicher Sicherheit unterstützt.

Die werden unterstützt und sind auch entsprechend übersichtlicher aus QuotedStr.

Delphi-Quellcode:
MyQuery1.SQL.Text := 'SELECT * FROM tabelle1 WHERE field1 = :wert1;';
MyQuery1.ParamByName('wert1').AsString := 'Hello World';
MyQuery1.Open;
Bei ParamByName werden automatisch die richten Zeichen gesetzt für die SQL-Abfrage und man braucht nicht mehr darauf zu achten, muss ich jetzt zum Beispiel Hochkommas schreiben oder nicht. Des weiteren wird das ganze so auch übersichtlicher.

DeddyH 9. Okt 2012 07:14

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Und vor allem sicherer im Bezug auf SQL-Injection. Außerdem werden IIRC Prepared Statements nur im Zusammenhang mit Parametern unterstützt, aber da kann ich natürlich auch irren.

Ykcim 9. Okt 2012 11:07

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo Zusammen,

Delphi-Quellcode:
MyQuery1.SQL.Text := 'SELECT * FROM tabelle1 WHERE field1 = :wert1;';
 MyQuery1.ParamByName('wert1').AsString := 'Hello World';
 MyQuery1.Open;
Das kannte ich nicht... Aber ich finde es richtig cool, weil es den Umgang mit den SQL-Anweisungen wirklich toll vereinfacht!

Habe es jetzt so umgesetzt:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Cols: TCols;
    Rows: TRows;
begin
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('select * from Benutzer where Vorname= :wert1');
  MyQuery1.ParamByName('wert1').AsString := Edit1.Text;
  connect(Form1.MyConnection1);
  ExecQuery(Form1.MyQuery1, Cols, Rows);
  FillGrid(StringGrid1, Cols, Rows);
  Disconnect(Form1.MyConnection1);
  showmessage('Stop');
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('update benutzer set Vorname= :wert2 where Vorname= :wert1');
  MyQuery1.ParamByName('wert1').AsString := Edit1.Text;
  MyQuery1.ParamByName('wert2').AsString := Edit2.Text;
  MyQuery1.Execute;
  MyQuery1.SQL.Clear;
  MyQuery1.SQL.Add('select * from Benutzer');
  connect(Form1.MyConnection1);
  ExecQuery(Form1.MyQuery1, Cols, Rows);
  FillGrid(StringGrid1, Cols, Rows);
  Disconnect(Form1.MyConnection1);

Was mich jetzt noch interessiert ist, wie Ihr das mit den Connection-Daten macht. Ich habe sie jetzt in einer Textdatei mit der Endung *.set. Aber dann könnte ja jeder diese auslesen und manuell auf den MySQL-Server gehen und das ist sicher nicht im Sinne des Erfinders.
Wie macht Ihr das? und was macht Ihr, wenn es z.B. mehrere mögliche Server gibt und Ihr dem zur Folge auch mehrere Verbindungsdaten habt?


Das zweite ist der Hinweis von Sir Rufo, dessen Sinn ich im ANsatz verstehen kann, aber ich gar keine Ahnung habe, wie ich das umsetzten soll.

Vielen Dank für die tollen Tips bis hierhin.

Ykcim

Medium 9. Okt 2012 11:20

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Wenn es schlecht ist, dass sich ein User mit diesen Daten direkt am SQL Server anmelden kann, dann hat dieser User zu viele Rechte ;). Mach einen User, der nur genau die Rechte hat, die dein Programm braucht, und keinesfalls den root oder sowas. Wenn dieser dann auch im Klartext lesbar ist, macht das nix.

DanielJ 17. Okt 2012 10:23

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo,

bei uns stehen die Verbindungsinformationen für die Verschiedenen Server in der Registry. Passwörter werden garnicht gespeichert, sondern beim Programmstart vom Nutzer angegeben.

Da kannst du auch machen was du willst - wenn du die Passwörter speicherst kann sie ein entsprechend versierte Nutzer auch auslesen.

Man kann sie zwar Verschlüsseln, aber der Key zum entschlüsseln befindet sich ja dann in der Exe und lässt sich per Debugger schnell finden.

LG,
Daniel

PS: Und dann kommt Firebird und macht alles zunichte in dem es die Passwörter im Klartext übers Netzwerk jagt ... :?

Ykcim 17. Okt 2012 12:41

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Die Passwörter für die Software werden natürlich nicht in einer File gespeichert, sondern in dem SQL-Server. Aber das Passwort für den Datenbank-Zugriff...

Gruß
Ykcim

Sherlock 17. Okt 2012 14:38

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Datenbankzugriffs-PW ist bei uns in der SW mehr oder weniger fest verdrahtet drin.

Sherlock

himitsu 17. Okt 2012 15:24

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Man sollte sie aber nicht unbedingt im OI (in der DFM) ablegen, sondern irgendwo per Code zuweisen.

Falls man nicht will, daß es per "Textsuche" im Code auffindbar ist (jenachdem wie das Pass"wort" aussieht), dann mit externem Programm verschlüsseln, verschlüsselt in den Quellcode kopieren und dort beim Zuweisen entschlüsseln lassen.

Mehr mühe braucht man sich nicht machen, denn jeder mit einem Compiler kann immernoch zum Aufruf der Passwortabfrage/-übergabe und sich dort den Inhalt der Variable (Speicherbereich im RAM) ansehn.
Und dann kann man eventuell auch noch ganz einfach die Connection zum DBServer belauschen (falls nicht verschlüsselt).

Sir Rufo 17. Okt 2012 18:02

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Es stellt sich die Frage, ob man überhaupt viel Energie in das Verstecken, Verschleiern oder Versonstwas mit den Zugangsdaten anstellen sollte.

Eine vernünftige Anwendung und vernünftig konfigurierter Server können dahingehend recht gut abgesichert werden, trotz bekannten Zugangsdaten sich keine Blöße zu geben.

Wer allerdings als Zugangsdaten den Root mitgibt, ja, der ist ja auch irgendwie selber Schuld gelle ;)

DanielJ 18. Okt 2012 09:17

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Naja,

z.B. im Callcenter währe es schon schädlich genug wenn einer mal eben per "select * from Kundendaten" die Adressen klaut - dann kann der Laden eigendlich dicht machen. Dafür reicht ja schon Lesezugriff!

Ein Kombination aus Programmbenutzer-Passwort und "geheimen" im quelltext/verschlüsselter Textdatei etc. verstecktem Passwortanteil kann hier zumindest die Hürde erhöhen. Man muss natürlich dann bei jeder Änderung des Programmbenutzers den passenden Datenbanknutzer mit ändern, aber das lässt sich ja automatisieren.

LG,
Daniel

Sir Rufo 20. Okt 2012 02:01

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Wer behauptet dass ein DB User direkten Zugriff (selbst rein lesend) auf die Tabellen haben muss?
Solch kritischen Datenzugriffe (wie du geschildert) würde ich immer über eine Stored Procedure laufen lassen.
Und dort kann ich mir jede Schweinerei ausdenken um den Zugriff auf das Allernötigste zu beschränken.

Desweiteren hat man immer die Möglichkeit eine weitere Schicht zwischen Client und DB Server zu setzen.

DanielJ 24. Okt 2012 09:13

AW: Anleitung zum Umgang mit Datenbank Komponenten
 
Hallo,

da hast du natürlich recht - bloß das muss erstmal einer bezahlen.
Ich habe leider noch keine Individualsoftware und wendig Standartsoftware gefunden, die da nicht erhebliche Mängel aufweist. Und wenn man den Kunde/Arbeitgeber darauf hinweist und dann erstmal wochenlange Restrukturierungsarbeiten/ das Erstellen eine Middleware vorschlägt, nehmen die meisten Klein- und Mittelständler lieber die Unsicherheit in kauf.
Dann kann man teilweise froh sein, wenn´s nicht allzuviele Proteste dagegen gibt, zumindest den SysDBA aus dem Quelltext zu entfernen und mal das Defaultpasswort zu ändern ... :cry:

LG,
Daniel


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:03 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-2025 by Thomas Breitkreuz