🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.delphi
Article #334597

ClientDatSet i Blob'y + D2010

#334597
From: Roman Wilk
Date: Sun, 08 Jan 2012 15:03
187 lines
6037 bytes
Witam,
Używam ClientDataSet'a np. do tworzenia / edycji praktycznie
wszystkich konstrukcji typu Master / Detalis (np. tworzenie pozycji
dokumentu FV, WZ itd). Kod w D7, który poniżej zamieszczam kopiował
(rekord po rekordzie, bo tak ma być)  zawartość zapytania zawartego w
IBQuery w ciągu maxymalnie kilku sekund (np. dla 1000 pozycji
dokumentu trwało to 3s).

function CopyDetailTable(localTable: TClientDataSet; detailTable:
TIBTable; masterTable: TIBTable;
  indexMasterValue: Variant; EmptyBefore: Boolean = True): Integer;
var
  i: Integer;
  IBQuery1: TIBQuery;
  FieldName: string;

procedure CopyRecord(localTable: TClientDataSet; query: TIBQuery);
var
  i: Integer;
  FieldName: string;
begin
  if not query.Active then
    query.Open;
  TableState(localTable);
  localTable.Append;
  for i := 0 to localTable.FieldCount - 1 do
  begin
    try
      FieldName := localTable.Fields[i].FieldName;
      if query.FieldList.Find(FieldName) = nil then
        continue;
      if localTable.FieldByName(FieldName).FieldKind = fkData then
        localTable.FieldByName(FieldName).Value :=
query.FieldValues[FieldName];
    except
    end;
  end;
  localTable.Post;
end;

begin
  IBQuery1 := TIBQuery.Create(Application);
  IBQuery1.Database := IBDLOG.IBDBKameleon;

  try
    localTable.DisableControls;
    if EmptyBefore then
      while not localTable.IsEmpty do
        localTable.Delete;
    Result := 0;
    TableState(localTable);
    if not ExistsRecord(detailTable.MasterFields,
masterTable.tableName, indexMasterValue) then
      exit;
    with IBQuery1 do
    begin
      Close;
      SQL.Add(Format('SELECT * FROM %s WHERE %s = :index',
[detailTable.tableName, detailTable.indexFieldNames]));
      ParamByName('index').Value := indexMasterValue;
      Open;
    end;
    IBQuery1.First;
    while not IBQuery1.Eof do
    begin
      CopyRecord(localTable, IBQuery1);
      IBQuery1.Next;
    end;
    Result := localTable.RecordCount;
  finally
    localTable.EnableControls;
    IBQuery1.Free;
    IBQuery1 := nil;
  end;

end;

Ten sam kod w D2010 robi to w ciągu 20 s (!!!???, czym to tłumaczyć,
Unicode ? Przecież IBQuery wszystkie stringi już zwraca jako
WideString, a w ClintDataSet są one zadeklarowane jako WideString),
poza tym ClientDataSet tworzy dynamicznie strukturę pól na podstawie
wzorca z TIBTable.

Ponieważ wydajność powyższego rozwiązania w kodzie wygenerowanym D2010
jest nie do przyjęcia. Zastąpiłem powyższe poniższym

procedure CopyRecords(DataSet: TClientDataSet;IBQuery: TIBQuery;
indexValue: Variant);
var
  tmp: TDataSetProvider;
  data: OleVariant;
  i: Integer;
  BlobFileCount: Integer;
  BlobFileName: array [0 .. 10] of string[100];

  function IsBlobFiledsExist: Boolean;
  var
    i, j: Integer;
  begin
    for i := 0 to 10 do
      BlobFileName[i] := '';
    Result := false;
    j := 0;
    for i := 0 to IBQuery.FieldCount - 1 do
      if IBQuery.Fields[i].DataType in [ftBlob,ftFmtMemo, ftMemo] then
      begin
        Result := True;
        BlobFileName[j] := IBQuery.Fields[i].FieldName;
        Inc(j);
      end;
  end;

  function GetBlobFileCount: Integer;
  var
    i: Integer;
  begin
    Result := 0;
    for i := 0 to 10 do
      if BlobFileName[i] <> '' then
        Result := i;

  end;

  function IsBlobValueExist(Field: TField): Boolean;
  begin
    Result := (not Field.IsNull) and (Field.AsString <> '');
  end;

  procedure CheckBlobFields;
  var
    i: Integer;
  begin
    if IsBlobFiledsExist then
    begin
      BlobFileCount := GetBlobFileCount;
      IBQuery.First;
      while not IBQuery.Eof do
      begin
        for i := 0 to BlobFileCount do
          if IsBlobValueExist(IBQuery.FieldByName(BlobFileName[i]))
then
            if
DataSet.Locate(indexValue,IBQuery.FieldByName(indexValue).AsVariant,
[]) then
            begin
              DataSet.Edit;
              DataSet.FieldByName(BlobFileName[i]).Value :=
IBQuery.FieldByName(BlobFileName[i]).Value;
              DataSet.Post;
            end;
        IBQuery.Next;
      end;
    end;
  end;

begin
  try
    tmp := TDataSetProvider.Create(nil);
    tmp.DataSet := IBQuery;
    DataSet.data := tmp.data;
    CheckBlobFields;
  finally
    tmp.Free;
  end;
end;

Ale jak widać z powyższego kodu, muszę sprawdzać czy w polach są
blob'y i ponownie je przepisać ponieważ samo :

    tmp.DataSet := IBQuery;
    DataSet.data := tmp.data;

niestety kopiuje tylko 1 znak z pola typu Blob

Na ClientDataSet są ustawione wszystkie potrzebne flagi np.
FetchOnDemand =:true


Czy ktoś ma może jakiś pomysł, jak zmusić taką konstrukcję do
kopiowania całej zawartości pól typu Blob ?






W tych rekordach są pola typu Blob
Technical Details
Message-ID: <447a7aff-3dd5-4e98-8f4f-becb9cf43a2c@k5g2000vba.googlegroups.com>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.nask.pl!news.nask.org.pl!goblin1!goblin.stu.neva.ru!postnews.google.com!k5g2000vba.googlegroups.com!not-for-mail

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.nask.pl!news.nask.org.pl!goblin1!goblin.stu.neva.ru!postnews.google.com!k5g2000vba.googlegroups.com!not-for-mail
From: Roman Wilk <kameleonsql@gmail.com>
Newsgroups: pl.comp.lang.delphi
Subject: ClientDatSet i Blob'y + D2010
Date: Sun, 8 Jan 2012 07:03:43 -0800 (PST)
Organization: http://groups.google.com
Lines: 188
Message-ID: <447a7aff-3dd5-4e98-8f4f-becb9cf43a2c@k5g2000vba.googlegroups.com>
NNTP-Posting-Host: 83.0.131.226
Mime-Version: 1.0
X-Trace: posting.google.com 1326036024 27931 127.0.0.1 (8 Jan 2012 15:20:24 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: Sun, 8 Jan 2012 15:20:24 +0000 (UTC)
Complaints-To: groups-abuse@google.com
Injection-Info: k5g2000vba.googlegroups.com; posting-host=83.0.131.226; posting-account=lJNmiQoAAAAcuwZEAibFvFBE7IgRs9bN
User-Agent: G2/1.0
X-Google-Web-Client: true
X-Google-Header-Order: ASELCHRU
X-HTTP-UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7,gzip(gfe)
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit