Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Denkblockade: Wie speicher ich ein Array in einer Datenbank? (https://www.delphipraxis.net/133512-denkblockade-wie-speicher-ich-ein-array-einer-datenbank.html)

Mithrandir 3. Mai 2009 20:52

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Hmm... WriteLN kann man aber nicht direkt für TStream nutzen, oder? :gruebel: Bei mir kommt immerhin die Meldung:

Zitat:

[Pascal Fehler] ORP_DataBase.pas(232): E2054 Ungültiger Typ in Write/Writeln-Anweisung

mkinzler 3. Mai 2009 21:02

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Und mit Write()?

Mithrandir 3. Mai 2009 21:09

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Genau dasselbe. Außerdem ist mir eingefallen, dass ich die Strings in der Länge begrenzen muss. Sonst weiß ich ja gar nicht, wo was anfängt und aufhört, wenn ich das ganze wieder auslesen will, oder?

mkinzler 3. Mai 2009 21:20

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Versuche es mal mit einem Zwischen-Stream.

String -> StringStream -> BlobStream -> Datenbankfeld

Mithrandir 3. Mai 2009 21:30

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Zitat:

Zitat von mkinzler
Versuche es mal mit einem Zwischen-Stream.

String -> StringStream -> BlobStream -> Datenbankfeld

Weißt du aus dem Kopf, ob folgende Idee auch klappen könnte?

Delphi-Quellcode:
//Größe des Records dank String[] bekannt
TORPTag = packed record
     Key:  String[255];
     Value: String[255];
  end;

  TORPTags = Array of TORPTag;

procedure WriteToDB(Tags: TORPTags);
var
 MemoryStream: TMemoryStream;
 i: integer;
begin
 MemoryStream := TMemoryStream.Create;
//...
 for i := Low(Tags) to High(Tags) do
  MemoryStream.Write(Tags[i], Sizeof(TORPTags));
//...
end;
Ich kanns grad leider nicht überprüfen... :stupid:

//Edit: Oder müsste dann das "Packed" raus? :gruebel:
//Edit2: Ist mal eben so aus dem Kopp getippt...

Dax 3. Mai 2009 21:45

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Das kann man ja nich mit ansehen :(
Delphi-Quellcode:
type
  TTag = record
    Key, Value: string;
  end;

  TTags = array of TTag;

procedure WriteInt(i: Integer; stream: TStream);
begin
  stream.Write(i, sizeof(i));
end;

function ReadInt(stream: TStream): Integer;
begin
  stream.Read(result, sizeof(result));
end;

procedure WriteString(s: string; stream: TStream);
begin
  WriteInt(Length(s), stream);
  stream.Write(s[1], Length(s));
end;

function ReadString(stream: TStream): string;
begin
  SetLength(result, ReadInt(stream));
  stream.Read(result[1], Length(result));
end;

procedure WriteTags(tags: TTags; stream: TStream);
var i: Integer;
begin
  WriteInt(Length(tags), stream);
  for i := 0 to High(tags) do begin
    WriteString(tags[i].Key, stream);
    WriteString(tags[i].Value, stream);
  end;
end;

function ReadTags(stream: TStream): TTags;
var i: Integer;
begin
  SetLength(result, ReadInt(stream));
  for i := 0 to High(Result) do begin
    tags[i].Key := ReadString(stream);
    tags[i].Value := ReadString(stream);
  end;
end;

Mithrandir 3. Mai 2009 21:48

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Zitat:

Zitat von Dax
Das kann man ja nich mit ansehen :(

Ist das mit mir wirklich so ein Trauerspiel? Ich weiß, ich konnt's mal besser... :cry:

Danke ;)

Mithrandir 7. Mai 2009 10:30

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Dax,

irgendwie funktioniert ein Teil deines Code nicht. Wenn ich mit ReadTags die Tags auslesen möchte, dann alloziiert er im ersten Durchlauf ~600 MB, den zweiten Durchlauf schafft er gar nicht mehr, weil er dann nicht genug Arbeitsspeicher hat.

Wenn ich mir diese Funktion ansehe, dann sollte man meinen, dass er 4 Byte liest:

Delphi-Quellcode:
function TORPDataBase.ReadInt(Stream: TMemoryStream): Integer;
begin
  stream.Read(result, sizeof(Integer));
end;
Stattdessen springt der Speicherverbrauch auf 600 MB... :gruebel:

[edit=mkinzler]Delphi-Tag eingefügt Mfg, mkinzler[/edit]

Dax 7. Mai 2009 14:05

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Vorweg: natürlich kann ich mich hinsichtlich der APIs irren, aber ich glaube, dass Read und Write Parameter (Pointer,Länge) hatten ;)

Ich bezweifle aber stark, dass es an der Methode liegt. Tritt das Problem denn immer auf, oder erst ab einer gewissen Tagmenge?

Mithrandir 7. Mai 2009 14:34

Re: Denkblockade: Wie speicher ich ein Array in einer Datenb
 
Zitat:

Zitat von Dax
Vorweg: natürlich kann ich mich hinsichtlich der APIs irren, aber ich glaube, dass Read und Write Parameter (Pointer,Länge) hatten ;)

Ich bezweifle aber stark, dass es an der Methode liegt. Tritt das Problem denn immer auf, oder erst ab einer gewissen Tagmenge?

Hi,

ja, das Verhalten tritt immer auf.

So schreibe ich die Knoten und die dazugehörigen Tags in die Datenbank:

Delphi-Quellcode:
procedure TORPDataBase.WriteNodeToDB(Node: TORPNode);
var
  Blob: TMemoryStream;
begin
  Blob := TMemoryStream.Create;
  Blob.Seek(0,soFromBeginning);
  try
    DecimalSeparator := '.';
    with fInsertNodeQuery do
    begin
      Connection := fConnection;
      ParamCheck := true;

      WriteTags(Node.tags, Blob);

      Params.CreateParam(ftBlob, 'tags', ptInput);
      ParamByName('tags').LoadfromStream(Blob, ftBlob);

      ParamByName('lon').AsFloat := StrToFloat(Node.Lon);
      ParamByName('lat').AsFloat := StrToFloat(Node.Lat);
      ParamByName('node_id').AsInteger := StrToInt(Node.ID);
      ExecSQL;
    end;
  finally
    FreeAndNil(Blob);
  end;
end;
Und so lese ich sie wieder aus:

Delphi-Quellcode:
function TORPDataBase.ReadNodesFromDB(): TORPNodes;
var
  BlobStream: TStream;
  Blob: TMemoryStream;
  fSelectNodeQuery: TZQuery;
  i: integer;
begin
  try
    DecimalSeparator := '.';
    fSelectNodeQuery := TZQuery.Create(nil);
    with fSelectNodeQuery do
    begin
      Connection := fConnection;
      ParamCheck := true;
      SQL.Text := 'SELECT * FROM NODES';
      Open;
      While not fSelectNodeQuery.Eof do
      begin
        Blob := TMemoryStream.Create;
        Blob.Seek(0,soFromBeginning);

        SetLength(Result,Length(Result)+1);
        i := High(Result);

        Result[i].ID := FieldByName('ID').AsString;
        Result[i].Lat := FieldByName('Lat').AsString;
        Result[i].Lon := FieldByName('Lon').AsString;

        BlobStream := CreateBlobStream(FieldByName('Tags'),bmRead);

        try
          Blob.CopyFrom(BlobStream, 0);
        finally
          FreeAndNil(BlobStream);
        end;

        Result[i].Tags := ReadTags(Blob);

        fSelectNodeQuery.Next;
      end;
    end;
  finally
    FreeAndNil(Blob);
  end;
end;
Jede wette, da steckt nur irgendein kleiner dämlicher Fehler drin? :gruebel:

Ich hatte tatsächlich die Tags vergessen? Oh man.. :gruebel:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:28 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz