AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi 'Fehler' im JoinTest von BetterADODataset
Thema durchsuchen
Ansicht
Themen-Optionen

'Fehler' im JoinTest von BetterADODataset

Ein Thema von Peinhard · begonnen am 11. Mär 2008
Antwort Antwort
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#1

'Fehler' im JoinTest von BetterADODataset

  Alt 11. Mär 2008, 15:02
Datenbank: MSSQL • Version: 8 • Zugriff über: ADO
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:
 
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;
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):

SELECT ID, Name, [_Description] = CASE WHEN [Description] IS NULL THEN '<Memo>ELSE '<MEMO>END FROM ItemTable 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:

Delphi-Quellcode:
  
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;
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:

Delphi-Quellcode:
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;
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:

Delphi-Quellcode:
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;
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.

Gruß an alle, Peinhard

P.S. Wenn das in die Code-Lib soll, bitte verschieben und/oder kurze Nachricht. Danke.
  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 07:18 Uhr.
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