[Erledigt] Objektlisten erstellen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

[Erledigt] Objektlisten erstellen

Beitrag von MacWomble »

Dank eurer Hilfe bin ich nun schon recht weit gekommen. Ich habe Klassen für einige meiner Tabellen erstell und diese getestet. So weit bin ich nun sehr zufrieden.
Die nächste Schritte, wo ich aus den Informationen im allwissenden Netz nichts wirklich passendes gefunden habe Liste der Objekte einer Klasse ('SELECT * FROM ArtikelGruppen') erstelle mit Create und Destroy (Ich kapiere das einfach nicht :oops: - oder ich finde nicht die richtige Anleitung dafür )

Da ich sicher nicht der Einzige bin, der sich am Anfang mit OOP schwer tut, halte ich das ganze etwas ausführlicher. Mit eurer Unterstützung entsteht dann eine Nachschlagewerk. :twisted:

Code: Alles auswählen

unit uartikelgruppe;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, LazLoggerBase, DBCtrls, dtm_basis;
 
type
 
  { TArtikelgruppe }
 
  TArtikelgruppe = class(TObject)
  private
    fIsChanged: boolean;
    fID: integer;
    fIDColor: integer;
    fArtikelgruppe: string;
  public
    constructor Create;
    destructor Destroy;
 
    procedure SetIDColor(const aValue: integer);
    procedure SetArtikelgruppe(const aValue: string);
 
    procedure Init;
    procedure ReadByID(ID: integer);
    procedure WriteData;
    procedure ReadData(Query: string);
  published
    // idartikelgruppe, artikelgruppe, fk_color
    property IsChanged: boolean read fIsChanged write fIsChanged default False;
    property ID: integer read fID write fID default -1;
    property IDColor: integer read fIDColor write SetIDcolor default 0;
    property Artikelgruppe: string read fArtikelgruppe write SetArtikelgruppe;
  end;
// ... und hier hänge ich erneut und benötige euer Wissen:
  TArtikelgruppenListe = class()  // Dachte das sollte TObjectlist sein, aber das geht nicht
    FArtikelgruppen: array of TArtikelgruppe;
  public
    constructor Create;
    destructor Destroy; override;
  end;
 
implementation
 
procedure TArtikelgruppe.SetIDColor(const aValue: integer);
begin
  if fIDColor = aValue then
    exit;
  fIDColor := aValue;
  IsChanged := True;
end;
 
procedure TArtikelgruppe.SetArtikelgruppe(const aValue: string);
begin
  if fArtikelgruppe = aValue then
    exit;
  fArtikelgruppe := aValue;
  IsChanged := True;
end;
 
 
constructor TArtikelgruppe.Create;
begin
  inherited Create;
  Init;
end;
 
procedure TArtikelgruppe.Init;
begin
  fID := -1;
  fIDColor := 0;
  fArtikelgruppe := '';
end;
 
procedure TArtikelgruppe.ReadByID(ID: integer);
begin
  ReadData('Select * from ArtikelGruppen where idartikelgruppe = ' + IntToStr(ID));
end;
 
procedure TArtikelgruppe.WriteData;
begin
  debugln('TArtikelgruppe.WriteData: ');
  if fIsChanged then
  begin
    fIsChanged := False;
    with dtmBasis.qrySQL do
    begin
      if fID < 0 then
      begin
        SQL.Clear;
        SQL.Add('Insert Into ArtikelGruppen');
        SQL.Add('(fk_color, artikelgruppe)');
        SQL.ADD('VALUES');
        SQL.ADD('(:fk_color, :artikelgruppe);');
        Prepare;
      end
      else
      begin  //Update
        DebugLn('  Datensatz ' + IntToStr(fid) + ' wird aktualisiert');
        SQL.Clear;
        SQL.ADD('UPDATE ArtikelGruppen SET');
        SQL.ADD('fk_color = :fk_color,');
        SQL.ADD('artikelgruppe = :artikelgruppe');
        SQL.ADD('WHERE idartikelgruppe = :idartikelgruppe;');
        Params.ParamByName('idartikelgruppe').AsInteger := fID;
      end;
      Params.ParamByName('fk_color').AsInteger := fIDColor;
      Params.ParamByName('artikelgruppe').AsString := fArtikelgruppe;
      try
        ExecSQL;
        DebugLn('  Gespeichert!');
        if fID = -1 then
        begin
          SQL.Text := 'SELECT * FROM view_lastid';
          Open;
          fID := FieldByName('LastID').AsInteger;
          debugLn('  Neue ID ist: ' + IntToStr(fID));
          Close;
        end;
      except
        On E: Exception do
          debugln(' ' + E.Message);
      end;
    end;
  end
  else
    DebugLn('  Nicht gespeichert: Datensatz aktuell');
end;
 
procedure TArtikelgruppe.ReadData(Query: string);
begin
  debugln('TArtikelgruppe.ReadData: ');
  with dtmBasis.qrySQL do
  begin
    try
      SQL.Text := Query;
      Open;
      fID := FieldByName('idartikelgruppe').AsInteger;
      fIDColor := FieldByName('fk_color').AsInteger;
      fArtikelgruppe := FieldByName('artikelgruppe').AsString;
      Close;
    except
      On E: Exception do
        debugln(' ' + E.Message)
    end;
  end;
end;
 
destructor TArtikelgruppe.Destroy;
begin
  inherited;
end;
 
 
end.
Zuletzt geändert von MacWomble am Mo 14. Jan 2019, 08:34, insgesamt 1-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

ich mache das immer so:
Hinweis: für TObjectList musst du die Unit: Contnrs mit einbinden.

Code: Alles auswählen

 
{ TPLNoteManagerDirectoryItemList }
  TPLNoteManagerDirectoryItemList = class
  private
    function GetCount: Integer;
    function GetItem(const aIndex: Integer): TPLNoteManagerDirectoryItem;
 
  protected
 
  public
    Items:TObjectList;
    constructor Create;
    destructor Destroy; override;
 
    procedure AddItem(aDirectoryItem:TPLNoteManagerDirectoryItem);
 
    property Count:Integer read GetCount;
    property Item[const aIndex:Integer]:TPLNoteManagerDirectoryItem read GetItem; default;
  published
  end; // TPLNoteManagerDirectoryItemList       
 
...
 
function TPLNoteManagerDirectoryItemList.GetCount: Integer;
begin
  result:=items.Count
end; // TPLNoteManagerDirectoryItemList.GetCount
 
function TPLNoteManagerDirectoryItemList.GetItem(const aIndex: Integer): TPLNoteManagerDirectoryItem;
begin
  result:=items[aIndex] as TPLNoteManagerDirectoryItem
end; // TPLNoteManagerDirectoryItemList.GetItem
 
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Das muss ich mir genauer anschauen.

Ich habe es inzwischen so versucht:

Code: Alles auswählen

 
uses ...Contnrs;
...
  TArtikelgruppenListe = class(TObjectList)
  private
    class var FItemClass: TArtikelgruppe;
  protected
    procedure SetItems(i: integer; const AValue: TArtikelgruppe);
    function GetItems(i: integer): TArtikelgruppe;
  public
    property Items[i: integer]: TArtikelgruppe read GetItems write SetItems;
    procedure Add(AObject: TArtikelgruppe);
    procedure Read;
    procedure Save;
    class property ItemClass: TArtikelgruppe read FItemClass write FItemClass;
    function FindByID(const AID: string): integer;
  end;     


Zuerst lesen, dann fragen :oops:
Du hast mir die Antwort ja geliefert, warum TObjectlist nicht ging.

Habe nun:
uartikelgruppe.pas(22,16) Warning: An inherited method is hidden by "destructor Destroy;"
uartikelgruppe.pas(65,13) Error: identifier idents no member "SetItems"
uartikelgruppe.pas(70,24) Error: identifier idents no member "GetItems"
Zuletzt geändert von MacWomble am So 13. Jan 2019, 14:27, insgesamt 1-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Ok, wenn ich es an deine Lösung anpasse, sind die Fehler weg :oops: - weitere Fragen in Kürze ... :roll:
Zuletzt geändert von MacWomble am So 13. Jan 2019, 14:44, insgesamt 2-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Code: Alles auswählen

property Items[i: integer]: TArtikelgruppe read GetItems write SetItems;

Hier reicht eigentlich ein read getItems.... Selten wird ein SetItems gebraucht....

Code: Alles auswählen

destructor TArtikelgruppe.Destroy;
begin
  inherited;
end;

Das würde ich vielleicht so machen:

Code: Alles auswählen

destructor TArtikelgruppe.Destroy;
begin
  inherited Destroy;
end;
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Danke!
Ich habe jetzt:

Code: Alles auswählen

TArtikelgruppenListe = class
  private
    function GetCount: integer;
    function GetItem(const aIndex: integer): TArtikelgruppe;
  protected
 
  public
    Items: TObjectList;
    constructor Create;
    destructor Destroy; override;
 
    procedure AddItem(aItem: TArtikelgruppe);
 
    property Count: integer read GetCount;
    property Item[const aIndex: integer]: TArtikelgruppe read GetItem; default;
  published
  end;
 
implementation
 
{ TArtikelgruppenListe }
 
function TArtikelgruppenListe.GetCount: integer;
begin
  Result := items.Count;
end;
 
function TArtikelgruppenListe.GetItem(const aIndex: integer): TArtikelgruppe;
begin
  Result := items[aIndex] as TArtikelgruppe;
end;
 
constructor TArtikelgruppenListe.Create;
begin
  inherited Create;
end;
 
destructor TArtikelgruppenListe.Destroy;
begin
  inherited Destroy;
end;
 
procedure TArtikelgruppenListe.AddItem(aItem: TArtikelgruppe);
begin
   inherited Add(aItem);
end;


Wie kommen die Daten aus der DB-Tabelle in die Liste?

Ich muss da ja eine Query mit 'SELECT * FROM ArtikelGruppen' absetzen. Dafür Dachte ich an eine procedure ReadAll, in welcher ich die DB öffne und Datensatz für Datensatz irendwie (mit AddItem?) in die ArtikelGruppenListe übernehme. Oder muß ich die einzeln anhand der ID dann in die TArtikelGruppe einlesen und dann mit AddItem übernehmen? Oder ganz anders?

Ich sehe Bäume, aber keinen Wald :oops:
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Ich sehe Bäume, aber keinen Wald

Das ist ganz einfach, du fügst sie hinzu.... Zum Beispiel so:

Code: Alles auswählen

 
procedure TPLNoteManager2.LoadDirectoryTableFromDB();
var
  Dir_Items:TObjectList;
 
  procedure BuildTreeNode(const aDirectoryID:Integer; aItems:TObjectList; aDirectoryItem:TPLNoteManagerDirectoryItem; const aLevel:Integer = 0);
  var
    i:integer;
    DirectoryItem:TPLNoteManagerDirectoryItem;
 
    TempDirectoryItem:TPLNoteManagerDirectoryItem;
  begin
    TempDirectoryItem:=nil;
    for i:=0 to aItems.Count-1 do begin
      DirectoryItem:=aItems[i] as TPLNoteManagerDirectoryItem;
      if (aDirectoryID = DirectoryItem.ParentID) then begin
        if (aLevel = DirectoryItem.Level) then begin
          if not Assigned(TempDirectoryItem) then
            TempDirectoryItem:=aDirectoryItem.AddItem(DirectoryItem)
          else
            TempDirectoryItem:=TempDirectoryItem.AddItem(DirectoryItem);
          BuildTreeNode(DirectoryItem.DirectoryID,aItems,TempDirectoryItem,aLevel+1);
          TempDirectoryItem:=TempDirectoryItem.Parent;
        end
      end;
 
    end; // for i
  end; // BuildTreeNode
var
  str:string;
  x:Integer;
  DirectoryItem:TPLNoteManagerDirectoryItem;
begin
  writeln('TEST');
  str:='select * from DirectoryTable;';
  MariaDB.Query.SQL.Text:=str;
  MariaDB.Query.ExecSQL;
  MariaDB.Query.Open;
 
  Dir_Items:=TObjectList.Create(false);
 
  if MariaDB.Query.RecordCount >= 0 then begin
    MariaDB.Query.First;
    while not MariaDB.Query.Eof do begin // not Query.Eof
      DirectoryItem:=TPLNoteManagerDirectoryItem.Create;
      for x:=0 to MariaDB.Query.Fields.Count-1 do begin
        if MariaDB.Query.FieldDefs[x].Name = 'id' then
          DirectoryItem.ID:=MariaDB.Query.Fields[x].AsInteger;
 
        if MariaDB.Query.FieldDefs[x].Name = 'DirectoryID' then
          DirectoryItem.DirectoryID:=MariaDB.Query.Fields[x].AsInteger;
 
        if MariaDB.Query.FieldDefs[x].Name = 'ParentID' then
          DirectoryItem.ParentID:=MariaDB.Query.Fields[x].AsInteger;
 
        if MariaDB.Query.FieldDefs[x].Name = 'Level' then
          DirectoryItem.Level:=MariaDB.Query.Fields[x].AsInteger;
 
        if MariaDB.Query.FieldDefs[x].Name = 'Name' then
          DirectoryItem.Name:=MariaDB.Query.Fields[x].AsString;
 
        if MariaDB.Query.FieldDefs[x].Name = 'CreatedateTime' then
          DirectoryItem.CreatedateTime:=MariaDB.Query.Fields[x].AsDateTime;
 
        if MariaDB.Query.FieldDefs[x].Name = 'LastReadDateTime' then
          DirectoryItem.LastReadDateTime:=MariaDB.Query.Fields[x].AsDateTime;
 
        if MariaDB.Query.FieldDefs[x].Name = 'LastwriteDateTime' then
          DirectoryItem.LastwriteDateTime:=MariaDB.Query.Fields[x].AsDateTime;
      end; // for x
 
      Dir_Items.Add(DirectoryItem);
      MariaDB.Query.Next;
    end; // while not
    BuildTreeNode(0,Dir_Items,DirectoryItemlist,0);
  end;
 
end; // TPLNoteManager2.LoadDirectoryTableFromDB
 


Das ist eine ganz besondere Proceduere, die kann aus der DirectoryTable eine Objekt Baum erzeugen, mit der man einfacher und schneller Arbeiten kann.
Diese Tabelle wird jetzt komplett eingelesen. Einmal beim Starten... und daraus wird dann der Objekt Baum erzeugt...
Aber ich denke, du siehst wie es gehen kann...

Es gibt bestimmt noch andere, vielleicht bessere Möglichkeiten.... Der Code stammt jetzt aus meinem Aktuellen Projekt... Aus dem Datenbaum möchte ich z.b. ein JSONEN Code erzeugen und an meine rest-clients versenden....
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

OK, das ist jetzt auch klar, Tabelle schrittweise einlesen und jeweils Objekt Der Artikelgruppe erstellen und in die Liste hinzufügen.

OffTopic: Die zweite Zeile kannst du doch weglassen.

Code: Alles auswählen

  MariaDB.Query.SQL.Text:=str;
  MariaDB.Query.ExecSQL; //wozu?
  MariaDB.Query.Open;
 
Zuletzt geändert von MacWomble am So 13. Jan 2019, 15:35, insgesamt 1-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

OffTopic: Die zweite Zeile kannst du doch weglassen.

Damit der SQL Befehl auch ausgeführt wird.... Ich weiß nicht ob ich ihn weglassen kann. Ich mache immer beides:
ExecSQL
und dann wenn gebraucht ein Open... weil ich brauche nicht immer ein Open...

EDIT: Ich habe den Soruce-Code von SQL eben angeschaut(nur grob), ich glaube nicht, dass man ExecSQL weglassen kann.
ExecSQL und Open haben ja nichts gemeinsam....
MFG
Michael Springwald

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Objektlisten erstellen

Beitrag von MacWomble »

Aber da du ja auf die Query anschließend zugreifst, brauchst du ein Open. Mit ExecSQL führst du den Befehl vorher schon aus (im Nirvana), machst also zwei mal den Zugriff auf die DB.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Aber da du ja auf die Query anschließend zugreifst, brauchst du ein Open. Mit ExecSQL führst du den Befehl vorher schon aus (im Nirvana), machst also zwei mal den Zugriff auf die DB.

glaube ich nicht, dass ich zwei mal den Zugriff mache, ich werde es aber bei nächster Gelegenheit testen.... Ich habe mir angeschaut was im Open Passiert, da steht nichts davon das dort ein ExecSQL..

Wenn ich mich täusche, werde ich es natürlich sofort umbauen...... sogar im FPC-Wiki steht es so drin.... alle andere machen es ähnlich(soweit ich weiß).
erst ein ExecSQL und dann ein Open....
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Du hast recht, es geht auch ohne "ExecSQL", habe ich eben ausprobiert... hätte ich jetzt nicht erwartet... Danke für den Hinweis...
MFG
Michael Springwald

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6199
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Objektlisten erstellen

Beitrag von af0815 »

Faustregel:
ExecSQL wenn man kein Recordset zurück erwartet. Zb. Create... Insert, update, delete.
Open wenn ein Recordset erwartet wird. Normalerweise bei einem Select. Natürlich bei visuellen Komponenten nötig, da diese ja immer an ein Recordset gebunden sind.

Btw, Recordset ist nicht gleich Query.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Objektlisten erstellen

Beitrag von pluto »

Faustregel:

war mir so nicht bewusst. Ich hatte es aus irgendwelchen Beispielen von fpc-wiki übernommen...
MFG
Michael Springwald

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Objektlisten erstellen

Beitrag von MmVisual »

Ich habe jetzt nicht alles gelesen ... aber:

Code: Alles auswählen

str:='select * from DirectoryTable;';


Schreibe immer die Tabellennamen in Kleinbuchstaben, denn sollte es mal ein Linux-Server sein, dann geht das sonst nicht mehr.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Antworten