![]() |
Datenbank: MSSQL • Version: 8 • Zugriff über: ADO
'Fehler' im JoinTest von BetterADODataset
To whom it may concern...
'Fehler' kann man es vielleicht nicht unbedingt nennen, etwas 'schlampig' bzw voreilig ist der JoinTest schon (zumindest mit MSSQL und Provider SQLOLEDB). Hier der Original-Code aus IsJoinedRecordSet:
Delphi-Quellcode:
Was ziemlich simpel darauf hinausläuft, dass bei einem Feld mit abweichendem Property 'BASETABLENAME' der JoinTest mit Ergebnis jtJoined beendet wird. Nun ist es aber so, dass vom Server berechnete Felder, zB mit folgendem SELECT (der zB verhindern soll, dass umfangreiche Memos oder Blobs für eine Gridanzeige tatsächlich geladen und zu einem client-seitigen Dataset transferiert werden):S:=VarToStr(RecordSet.Fields[0].Properties[cBaseTableName].Value); For I:=Pred(RecordSet.Fields.Count) DownTo 1 Do With RecordSet.Fields Do begin If (S<>VarToStr(Item[I].Properties[cBaseTableName].Value)) Then Begin Result:=jtJoined; Break; End;
SQL-Code:
in den Feld-Properties mit Value NULL (nach VarToStr also '') für BaseTableName geführt wird, der JoinTest also fälschlich jtJoined zurückgibt. Das kann man natürlich umgehen bzw 'austricksen', indem man die Unique_-Properties setzt, man könnte aber auch beim JoinTest selbst ansetzen, in diesem Fall und unter der Annahme, dass solcherart berechnete Felder immer mit einem Unterstrich beginnen zB so:
SELECT ID, Name, [_Description] = CASE WHEN [Description] IS NULL THEN '<Memo>' ELSE '<MEMO>' END FROM ItemTable
Delphi-Quellcode:
Oder etwas allgemeingültiger und unter Berücksichtigung der Tatsache, dass der Treiber für die in Frage stehenden Felder auch die Property 'BASECOLUMNNAME' mit NULL zurückgibt:S := VarToStr(RecordSet.Fields[0].Properties[cBaseTableName].Value); for I := pred(RecordSet.Fields.Count) downto 1 do begin SI := VarToStr(RecordSet.Fields.Item[I].Properties[cBaseTableName].Value); if (S <> SI) and not ((SI = '') and (Pos('_',Fields[i].FieldName) = 1)) then begin Result := jtJoined; Break; end; end;
Delphi-Quellcode:
Die entsprechenden Variablen und Konstanten sind natürlich zu definieren. Es empfiehlt sich auch, für jede Kombination von DB und Treiber die Rückgabewerte der Properties nochmal gesondert zu untersuchen, wozu folgender Code dienen mag:
S := VarToStr(RecordSet.Fields[0].Properties[cBaseTableName].Value);
for I := pred(RecordSet.Fields.Count) downto 1 do begin SB := VarToStr(RecordSet.Fields.Item[I].Properties[cBaseTableName].Value); SC := VarToStr(RecordSet.Fields.Item[I].Properties[cBaseColumnName].Value); if (S <> SB) and not ((SB = '') and (SC = '')) then begin Result := jtJoined; Break; end; end;
Delphi-Quellcode:
Der Code gibt eine INI-ähnliche Liste zurück, die mit den StringList-Eigenschaften Name und Value gut ausgewertet oder in einem Memo dargestellt werden kann. Auch sehr interessant ist nebenbei bemerkt das (prinzipiell gleiche) Auslesen der Properties des Connection- wie des RecordSet-Objektes. Dort wird bei besagtem Treiber übrigens im Zweifelsfall nicht NULL, sondern ein 'empty variant' für nicht gesetzte Werte zurückgegeben, daher der entsprechende Code in VarToStrVerbose.
uses ..., ADO26_TLB, ...;
function VarToStrVerbose(const V: Variant): string; begin if VarIsEmpty(V) then Result := '<not assigned>' else if VarIsArray(V) then Result := '<array>' else if VarIsNull(V) then Result := '<null>' else Result := VarToStr(V); end; procedure FieldProperties(ASet: TBetterADODataset; AList: TStrings; Index: integer=-1); procedure FieldProps(ASet: TBetterADODataset; AList: TStrings; Index: integer); var sN,sV: string; vV: Variant; i: integer; begin with ASet do begin for i:=0 to pred(RecordSet.Fields[Index].Properties.Count) do begin sN := RecordSet.Fields[Index].Properties[i].Name; vV := RecordSet.Fields[Index].Properties[i].Value; sV := VarToStrVerbose(vV); AList.Add(sN+'='+sV); end; end; end; var i: integer; begin AList.Clear; if (Index = -1) then begin for i:=0 to pred(ASet.Fields.Count) do begin AList.Add('['+ASet.Fields[i].FieldName+']'); FieldProps(ASet,AList,i); AList.Add(''); end; end else begin AList.Add('['+ASet.Fields[Index].FieldName+']'); FieldProps(ASet,AList,Index); end; end; Gruß an alle, Peinhard P.S. Wenn das in die Code-Lib soll, bitte verschieben und/oder kurze Nachricht. Danke. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:55 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 by Thomas Breitkreuz