AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Parameter unter Firedac
Thema durchsuchen
Ansicht
Themen-Optionen

Parameter unter Firedac

Ein Thema von Delbor · begonnen am 4. Mär 2016 · letzter Beitrag vom 11. Mär 2016
Antwort Antwort
Delbor

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

AW: Parameter unter Firedac

  Alt 7. Mär 2016, 13:59
Hi zusammen
Zitat:
---------------------------
Im Projekt ContentMasterDXE8.exe ist eine Exception der Klasse EFDException mit der Meldung '[FireDAC][Phys][MySQL]-335. Datentyp des Parameters [LFOLDERID] ist unbekannt. Hinweis: Geben Sie TFDParam.DataType an, oder weisen Sie den TFDParam-Wert vor dem "Prepare"/"Execute"-Aufruf zu' aufgetreten.
---------------------------
Das ist die Fehlermeldung, die ich gerade eben erhalten habe. Und so versuche ich, das Ergebnis aus GuidToString in die DB zu bekommen:
Delphi-Quellcode:
function TFDMySQLDml.BildInsertQuery(LThumbMemory: TMemoryStream; LFolderID: TMemoryStream): integer;
  var SQLString: string; AUser,APass :string;
begin
  SQLString := 'Insert Into Bildtabelle(Thumbnail, FolderID) Values (:LThumbMemory, :LFolderID)';
  FDQueryMain.SQL.Text := SQLString;
  FDQueryMain.Params[0].LoadFromStream(LThumbMemory, ftgraphic);
  FDQueryMain.Params[0].LoadFromStream(LFolderId, ftstring); //<==
  FDQueryMain.ExecSQL(false);
...
Ursprünglich hatte ich den Datentyp für das Feld mit ftguid angegeben, aber da meckerte Delphi einige seltsame (unbekannte) Zeichen an.
Erzeugt wird die Guid so:
Delphi-Quellcode:
    ....
    if not FileExists(LPath+'IdentFile.cgf') then
    begin // ist in dem Ordner kein IdentifikationsFile
      FolderID := CreateIDFile(LPath);
      Self.FIDFile := FolderID; /// wird eines angelegt
    end;

function TOpenFileFrame.CreateIDFile(LPath : String): String;
  var IdFile : TFileStream; ID_GUID: TGUID;
      UniqueName: String; Len: Longint;
begin
  if CreateGUID(ID_GUID) <> 0 then
     Result := 'Creating GUID failed!'
  else
  begin
     UniqueName := GUIDToString(ID_GUID);
     IdFile := TFileStream.Create(LPath,fmCreate);
     try
       Len := Length(UniqueName);
       IdFile.Write(Len, SizeOf(Len));
       IdFile.Write(PChar(UniqueName)^, Len);
     finally
      IdFile.Free;
     end;
     Result := 'IdentFile.cgf';
  end;
end;
Was mache ich falsch?

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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.386 Beiträge
 
Delphi 12 Athens
 
#2

AW: Parameter unter Firedac

  Alt 7. Mär 2016, 14:05
LFolderId = IdentFile.cgf ?
Binärdaten in einen String laden?

Delphi-Quellcode:
Params[0]
Params[0]


FDQueryMain.Params[1].AsAString := TFile.ReadAllText(LFolderId); // natürlich nur, wenn da wirklich nur "Text" in der Datei ist
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Delbor

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

AW: Parameter unter Firedac

  Alt 9. Mär 2016, 16:40
Hi Himitsu

Danke für den Tip! Entsprechend habe ich das wie folgt abgeändert
Delphi-Quellcode:
function TFDMySQLDml.BildInsertQuery(LThumbMemory: TMemoryStream; FolderId: string): integer;
  var SQLString: string; AUser,APass :string;
begin
  SQLString := 'Insert Into Bildtabelle(Thumbnail, FolderID) Values (:LThumbMemory, :FolderID)';
  FDQueryMain.SQL.Text := SQLString;
  FDQueryMain.Params[0].AsStream := LThumbMemory;
  FDQueryMain.Params[1].AsString := FolderID;
  FDQueryMain.ExecSQL(false);
....
und
Delphi-Quellcode:
function TOpenFileFrame.CreateIDFile(LPath : String): String;
  var IdFile : TFileStream; ID_GUID: TGUID;
      UniqueName: String; Len: Longint;
begin
  if CreateGUID(ID_GUID) <> 0 then
     Result := 'Creating GUID failed!'
  else
  begin
     UniqueName := GUIDToString(ID_GUID);
     IdFile := TFileStream.Create(LPath,fmCreate);
     try
       Len := Length(UniqueName);
       IdFile.Write(Len, SizeOf(Len));
       IdFile.Write(PChar(UniqueName)^, Len);
     finally
      IdFile.Free;
     end;
     Result := UniqueName;
  end;
end;
Meine letzte Fehlermeldung:
Zitat:
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt ContentMasterDXE8.exe ist eine Exception der Klasse EMySQLNativeException mit der Meldung '[FireDAC][Phys][MySQL] Data too long for column 'FolderID' at row 1' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
Das Feld in der DB ist jetzt ein Varchar(80). Max_allowed_packet (Maximale Packetgrösse) hat jetzt den Wert 16M. Beide Werte sollten nicht zu klein sein, um den Guidstring zu speichern.

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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.386 Beiträge
 
Delphi 12 Athens
 
#4

AW: Parameter unter Firedac

  Alt 9. Mär 2016, 17:51
hmmmmmmmmm

Etwas in dieser Richtung geht auch nicht?
Delphi-Quellcode:
FDQueryMain.SQL.Text := 'SELECT Thumbnail, FolderID FROM Bildtabelle WHERE 0'; // LIMIT 0
FDQueryMain.Open;
FDQueryMain.Insert;
FDQueryMain.FieldByName('Thumbnail').AsStream := LThumbMemory;
FDQueryMain.FieldByName('FolderID').AsString := FolderID;
FDQueryMain.Post;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Delbor

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

AW: Parameter unter Firedac

  Alt 9. Mär 2016, 20:42
Hi Himitsu

Ich bin überzeugt, dass es mit der SQL-Syntax nichts zu tun hat. Es hat ja nicht nur unter DBExpress, sondern auch unter FireDac funktioniert, bis ich der Tabelle das zusätzliche Feld verpasst habe.
Beim letzten Versuch habe ich mal ein Showmessage eingebaut. Das Resultat:
[Window Title]
Zitat:
Contentmasterdxe8

[Content]
Size of FolderId := 4

[OK]
Hmm... Variablen sind ja eigentlich Zeiger, und die sind 4 Bytes gross...

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

Geändert von Delbor ( 9. Mär 2016 um 20:46 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.386 Beiträge
 
Delphi 12 Athens
 
#6

AW: Parameter unter Firedac

  Alt 10. Mär 2016, 10:04
Wenn da 4 bei raus kommt, dann ist irgendwas "kaputt".

TField.Size = bei VARCHAR(MaxLength) sollte MaxLength raus kommen
TField.DataSize = bei VARCHAR(MaxLength) als WideStringField sollte 2+MaxLength*2 raus kommen
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Parameter unter Firedac

  Alt 10. Mär 2016, 10:24
Delphi-Quellcode:
function TOpenFileFrame.CreateIDFile(LPath : String): String;
  var IdFile : TFileStream; ID_GUID: TGUID;
      UniqueName: String; Len: Longint;
begin
  if CreateGUID(ID_GUID) <> 0 then
     Result := 'Creating GUID failed!'
  else
  begin
     UniqueName := GUIDToString(ID_GUID);
     IdFile := TFileStream.Create(LPath,fmCreate);
     try
       Len := Length(UniqueName);
       IdFile.Write(Len, SizeOf(Len));
       IdFile.Write(PChar(UniqueName)^, Len);
     finally
      IdFile.Free;
     end;
     Result := UniqueName;
  end;
end;
Könntest du mal erklären wozu du das benötigst?

Du schreibst da einen GUID-String in eine Datei ... aber wozu? Um diesen String als Stream zu haben?

Nicht wirklich, oder etwa doch?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Delbor

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

AW: Parameter unter Firedac

  Alt 10. Mär 2016, 13:27
Hi zusammen

@Sir Rufo

Zitat:
Nicht wirklich, oder etwa doch?
Diese Datei soll den Ordner, der die Rohdaten der importierten Bilder enthält, kennzeichnen. Der Tip mit dieser Guid stammt übrigens von dir.
Gleichzeitig soll der vergebene GUID in der DB gespeichert werden.

Allerdings ist mir ein Designfehler unterlaufen. Ich habe das Feld für den GUID der Bildtabelle verpasst, aber eigentlich gehört das Ding in die Kategorientabelle - die enthält "Kategorien" (diesen Namen habe ich seinerzeit falsch gewählt), die jedoch eigentlich den Ordnernamen auf der Festplatte entsprechen. Diese Ordner enthalten meist Fotos, die bei einem bestimmten Ereignis entstanden sind, können aber auch solche enthalten, die sich auf mehrere Ereignisse beziehen.

@Himitsu:
Zitat:
Wenn da 4 bei raus kommt, dann ist irgendwas "kaputt".
Kaputt wohl nicht - ich habs wohl einfach falsch gemacht...
Showmessage('Size of UniqueNameUniqueName := ' + IntToStr(SizeOf(UniqueName))); Da ich die Bytes wissen wollte, habe ich Size verwendet. Wobei mir das Leerzeichen nach Size erst jetzt auffällt...

Gruss
Delbor

PS: Dacht ichs doch: Wenn ich SizeOf durch Length ersetze, siehts ganzanders us:
[Window Title]
Zitat:
Contentmasterdxe8

[Content]
Size of UniqueName := 38
[OK]
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (10. Mär 2016 um 13:34 Uhr)
  Mit Zitat antworten Zitat
Delbor

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

AW: Parameter unter Firedac

  Alt 10. Mär 2016, 14:08
Hi zusammen
Im Moment siehts ganz danach aus, als ob die DB den String/Stream akzeptiert:
Delphi-Quellcode:
procedure TOpenFileFrame.Btn_OkClick(Sender: TObject);
  var AUser,APass, Bildpfad, LPath : String;
      FolderID : TStringstream; LIdFolder: String; // <=Da Fettdarstellung innerhalb der Delphi-Tags nicht funktioniert - die Änderungen
      LPathCount, i: integer;
begin
  LPathCount := Self.FPathlist.Count;
  CM_First.CreateProgressbarDlg(LPathCount); // Create den ProgressbarDialog und zeigt ihn an // Dazu braucht das System etwas Zeit
  try
    CM_First.ProgressbarDlg.Top := 20;
    CM_First.ProgressbarDlg.Left := (CM_First.ProgressbarDlg.Monitor.Width - CM_First.ProgressbarDlg.Width) div 2;
    Application.ProcessMessages;
    FDMySQLDml.Pathlist.AddStrings(FPathlist);
    CM_First.Listbox1.Items.AddStrings(FPathlist);
    Bildpfad := FPathList[0];
    LPath := ExtractFilePath(Bildpfad)+'IdentFile.cgf';
    if not FileExists(LPath+'IdentFile.cgf') then
    begin // ist in dem Ordner kein IdentifikationsFile
      FolderID := TStringstream.Create;
      LIdFolder := CreateIDFile(LPath);
      FolderID.WriteString(LIdFolder); /// wird eines angelegt
    end;
    if FDMySQLDml.DefineContentmasterConnection then
    begin
      try
        FDMySQLDml.FDConnectionMySql.StartTransaction;
        FDMySQLDml.BildTabelleInsert2(100, FolderID); // Startet die Insert-Prozeduren
        FDMySQLDml.FDConnectionMySql.Commit;
      except
        FDMySQLDml.FDConnectionMySql.Rollback;
      end;
    end;
  finally
      CM_First.ProgressbarDlg.FormStyle := fsnormal;
      CM_First.ProgressbarDlg.Close;
      FreeAndNil(CM_First.ProgressbarDlg);
      if assigned(FolderID) then
        FolderID.Free;
  end;
end;
Für einmal die komplette Prozedure, welche die Inserts startet. Die Änderungen sind fett dargestellt.
Delphi-Quellcode:
procedure TFDMySQLDml.BildTabelleInsert2(Seitenlaenge: Integer; FolderID: TStringstream);
  var BMap: TBitmap; BJpeg: TJPEGImage; SQLString,Bildname, Bildpfad: String;
       BildTabelleLastId,IDBild, i,inserted : Integer; LPicture : TPicture;
       LThumbMemory : TMemoryStream;
begin
  LThumbMemory := TMemoryStream.Create;
  LPicture := TPicture.Create;
  BMap := TBitmap.Create; //Lokal
  BJpeg := TJpegImage.Create; //Lokal
  BJpeg.CompressionQuality := 100;
  BJpeg.PixelFormat := jf24Bit;
 try
    FTotal := FPathList.Count;
    for i := 0 to FPathList.Count - 1 do
    begin
      FRest := FPathList.Count - i;
      if FDQueryMain.Active then
        FDQueryMain.Active := False;
      Bildname := ExtractFileName(FPathList[i]);
      Bildpfad := FPathList[i];
      Delete(BildName,Length(BildName)-3,4);
        LThumbMemory.Clear; //<= Beim 2. durchlauf gibts hier eine AV
        if ExtractFileExt(FPathList[i]) = '.NEFthen
        begin
          LPicture.LoadFromFile(FPathList[i]);
          BMap.Assign(LPicture.Graphic);
          FModifyBitmap.ScaleBitmaps(BMap, Seitenlaenge);
          BJpeg.Assign(BMap);
          BJpeg.SaveToStream(LThumbMemory);
          BildTabelleLastId := BildInsertQuery(LThumbMemory, FolderId);
          FReportList.Add(' '+ IntToStr(i)+'-TPicAdmin.BildTabelleInsert2');
          FReportList.Add(' ');
          BildDescribeTabelleInsert(BildTabelleLastId,BildName,Bildpfad); //Ab hier werden nacheinander die Insert-Prozeduren
          inserted := 1; //aufgerufen
          if Assigned(FOnInsertedRecord) then //<== Hier wird das Event gefeuert; zu dem Zeitpunkt wurde
            FOnInsertedRecord(Self,inserted); //<== ein Datensatz über die verschiedenen Tabellen eingefügt
        end;
    end;
  finally
    LThumbMemory.Free;
    FreeAndNil(BJpeg);
    FreeAndNil(BMap);
    FreeAndNil(LPicture);
  end;
end;
In der 2. Prozedur wird die Iteration durch die Pfadliste begonnen, wobei beim 2. Durchlauf eine AV ausgelöst wird, wenn LThumbMemory geleert werden soll. Wie aber ersichtlich ist, wiird LThumbMemory erst nach getaner Arbeit freigegeben.
Da ich LThumbMemory als Parameter übergebe, kamm mir die Idee, Firedac gäbe den Stream nach getaner Arbeit frei. Das aber kannnicht sein, da ein Probelauf schonmal funktioniert hatte.

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

Geändert von Delbor (10. Mär 2016 um 14:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Parameter unter Firedac

  Alt 10. Mär 2016, 15:05
Ersichtlich ist da gar nichts, denn wir können nicht sehen, was in BildInsertQuery mit dem Stream passiert.

BTW
  • Diese Kopierorgie mit Picture, Bitmap, JpegImage, Stream ist schon sehr abstrus und könnte bequem auf ein Picture und JpegImage reduziert werden
  • Eine GUID als StringStream ist auch sehr merkwürdig
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (10. Mär 2016 um 15:11 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:02 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