Article View: pl.comp.lang.delphi
Article #334597ClientDatSet i Blob'y + D2010
From: Roman Wilk
Date: Sun, 08 Jan 2012 15:03
Date: Sun, 08 Jan 2012 15:03
187 lines
6037 bytes
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-mailShow 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