Einzelnen Beitrag anzeigen

Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#29

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 16:14
Hi zusammen

TQueryResultClass arbeitet schon länger zur vollkomenen Zufriedenheit - das Problem, das ich mit dem Threadtitel angesprochen habe, war: Gäbe es eine OOP-Lösung, um TQueryResultClass zu ändern? Änderungsziel: Gleiches Funktionieren, wie ursprünglich implementiert, aber mit andern Bezeichnern. Aber erstmal, was TQueryResultClass tut (und mehr hat diese Klasse auch nicht zu tun):
Delphi-Quellcode:
procedure TFDMySQLDml.SelectBildDaten(FCategoryKey : Integer);
  var SQLString: String; Kath_Id : integer;
begin
  Kath_Id := FCategoryKey;
  SQLString := DefineBildSQL3(Kath_Id); // Liefert den SQL-String zurück
  FDQueryMain.Connection := Self.FDConnectionMySql;
  FDQueryMain.Close;
  FDQueryMain.SQL.Text := SQLString;
  FDQueryMain.Params.CreateParam(ftInteger, 'Kath_Id', ptOutput);
  FDQueryMain.Params[0].AsInteger := Kath_Id;
  FDQueryMain.Open;
  FDQueryMain.First;
  While (Not FDQueryMain.Eof) do
  begin
    FQueryResult := TQueryResultClass.Create(Self);
    FQueryResult.IdBild := (FDQueryMain.FieldByName('BildId').AsInteger);
    [QUOTE]FQueryResult.BildDescribeTabelle.BilddesribeID := FDQueryMain.FieldByName('BildDescribeId').AsInteger;[/QUOTE]
    FQueryResult.BildDescribeTabelle.bildkatID := FDQueryMain.FieldByName('bildkatID').AsInteger;
    FQueryResult.BildDescribeTabelle.BildName := FDQueryMain.FieldByName('BildName').AsString;
    FQueryResult.BildDescribeTabelle.BildBeschreibung := FDQueryMain.FieldByName('Bildbeschreibung').AsString;
    FQueryResult.BildDescribeTabelle.BildLegende := FDQueryMain.FieldByName('Bildlegende').AsString;
    FQueryResult.KategoryTabelle.Kategory := FDQueryMain.FieldByName('Kategorie').AsString;
    FDQueryMain.Next;
    FCategoryBildlist.Add(FQueryResult); // Die Records in TQueryResultClass müssen überprüft werden.
  end;
  FDQueryMain.Close;
end;
Wie ersichtlich ist: Weder das Query noch TQueryResultClass verfügen in dieser Abfrage über einen Stream für Blobdaten. Interesieren tun hier nur gerade mal die Begleitdaten zum Bild.
Das besondere, weswegen es TQueryResultClass überhaupt gibt, sind seine Bilder-Propertis:
Delphi-Quellcode:
    property Thumbnail: TMemoryStream read GetThumbnail write SetThumbnail;
    property Bitmap: TMemoryStream read GetBitmap write SetBitmap;
Die beiden Getter, aam Beispiel von GetThumbnail:
Delphi-Quellcode:
function TQueryResultClass.GetThumbnail: TMemoryStream;
  var AUser, APass : String;
begin
  if not Assigned(FThumbnail) then
  begin
    FThumbnail := TMemorystream.Create;
    Result := FillThumbnail(FThumbnail);
  end else
    Result := FThumbnail;
end;
Die Funktion Fillthumbnail:
Delphi-Quellcode:
function TQueryResultClass.FillThumbnail(var Thumbnail: TMemoryStream):TMemoryStream;
var
  BildID: Integer;
  BlobStream: TStream;
  LNull: string;
  SQLString: string;
begin
    BildID := Self.FidBild;
    SQLString := 'SELECT Bildtabelle.Thumbnail as Thumbnail FROM Bildtabelle WHERE Bildtabelle.idBild = :BildID';
    FDMySQLDml.FDQueryMain.SQL.Text := SQLString;
    FDMySQLDml.FDQueryMain.Params.CreateParam(ftInteger, 'BildID', ptInput);
    FDMySQLDml.FDQueryMain.Params[0].AsInteger := BildID;
    FDMySQLDml.FDQueryMain.Open;
    FDMySQLDml.FDQueryMain.First;
    while not FDMySQLDml.FDQueryMain.Eof do
    begin
      if not FDMySQLDml.FDQueryMain.FieldByName('Thumbnail').IsNull then
      begin
        BlobStream := FDMySQLDml.FDQueryMain.CreateBlobStream(FDMySQLDml.FDQueryMain.FieldByName('Thumbnail'), bmread);
        BlobStream.Position := 0;
        FThumbnail.CopyFrom(BlobStream, Blobstream.Size);
        BlobStream.Free;
        FDMySQLDml.FDQueryMain.Next;
        Result:= FThumbnail;
      end
      else
      begin
        LNull := 'Kein Thumbnail vorhanden';
        FThumbnail.WriteBuffer(LNull, SizeOf(LNull));
      end;
    end;
    FDMySQLDml.FDQueryMain.Close;
end;
Das ist das, was geschieht, wenn zur Darstellung der Datensätze auch auf die Bildpropertys von TQueryResultClass zugegriffen wird.

Und nochmal zur Übereinstimmung von Klassen-/Feld und Tabellen/Feldnamen: Der Klasse tuts nicht weh, wenn ihre Felder gleich heissen, wie diejenigen der Tabelle, und zu Fehlfunktionen kann es auch nicht kommen. Aber was liest sich besser:
Delphi-Quellcode:
FQueryResult.BildDescribeTabelle.bildkatID := FDQueryMain.FieldByName('bildkatID').AsInteger;
// oder
FQueryResult.Id := FDQueryMain.FieldByName('bildkatID').AsInteger;
Von den drei beteiligten Tabellen hat jede eine Id als Primärschlüssel und eine als Fremdschlüssel,und alle sind sie wichtig. Bei übereinstimmenden Namen kannst du in der Zuweisung nicht irren, bei grundsätzlich verschiedenen Namen hingegen schon.

Zitat von DeddyH:
Zitat:
Je mehr ich lese, desto mehr frage ich mich: wozu das Ganze? Soll das ein ORM werden/sein? Dann haben IMO die Tabellen- bzw. Feldnamen in den Objekten nichts zu suchen, die Objekte sollte es nicht interessieren, woher die Daten kommen oder wohin sie gehen, dafür ist eine Schicht zuständig. So wie ich es sehe bringt der ganze Aufwand momentan 0% Nutzen (sofern ich das richtig überblicke, ich kann mich auch irren), sondern sorgt eher für Verwirrung.
Gewissermassen ja. Das ganze, insbesondere der Teil mit dem Nachladen der Bilddaten, ist unter anderem mit deiner tatkräftigen Mithilfe (auf Delphi Treff) entstanden. Dein Kommentar damals: "Ein Mini-Orm".
Ein ORM bildet ja eine komplette Datenbank mit Hilfe von zB. Delphi-Objekten ab. Aber eben eine komplette Datenbank. Meine Klasse gestattet das Nachladen der Bilddaten bei Bedarf und das Iterieren durch die Ergebnismenge bei geschlossenem Query oder sogar geschlossener Verbindung, mehr nicht.


Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat