Fragen zum Sortieren, Durchsuchen, Suchen und Filtern (FireDAC)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu FAQ (FireDAC)

Dieses Thema enthält eine Liste mit Fragen und Antworten zum Sortieren, Durchsuchen, Suchen und Filtern von Datenmengen.

F1: In der Datenmenge werden nicht-englische Strings falsch sortiert. Ich erhalte auch den Fehler "[FireDAC][DatS]-2. Objekt [] nicht gefunden". Was ist falsch?

A: Führen Sie die folgenden Schritte aus, um dieses Problem zu beheben:

  • Öffnen Sie $(BDS)\source\data\firedac\FireDAC.inc.
  • Suchen Sie die Zeilen:
 {$define FireDAC_NOLOCALE_DATA}   // define to use binary data comparison
 {$define FireDAC_NOLOCALE_META}   // define to use binary metadata comparison
  • Kommentieren Sie sie aus.
  • Speichern Sie die Datei, und compilieren Sie die Anwendung erneut.

Hinweis: Wenn Sie nur mit englischen (ASCII-)Texten arbeiten, sollten Sie die obigen Zeilen nicht auskommentieren. Dadurch werden Sortier- und Suchvorgänge erheblich beschleunigt.

F2: Muss zum Sortieren von Daten ein Index erstellt werden?

A: Sie müssen keine Indizes definieren, wenn Sie die Tabelle nur sortieren möchten. Dies wird durch IndexFieldNames erledigt. Indizes ermöglichen die Definition von Sichten, die eine Mischung aus Filter- und Sortiervorgängen darstellen. Bei allen FireDAC-Datenmengen schließen sich Indizes und IndexDefs gegenseitig aus. Das bedeutet, dass Sie entweder Indizes oder IndexDefs verwenden sollten, aber nicht beides.

F3: Können in Indexdefinitionen Nachschlagefelder verwendet werden?

A: Nein. Aber Sie können interne berechnete Felder in Indizes verwenden. Fügen Sie dazu persistente Felder hinzu, fügen Sie dann ein fkInternalCalc-Feld hinzu, erstellen Sie OnCalcFields-Ereignisbehandlungsroutinen, und berechnen Sie dieses Feld in der Ereignisbehandlungsroutine. Zum Beispiel:

 procedure TForm21.FDTable1CalcFields(DataSet: TDataSet);
 begin
   DataSet.FieldByName('f_calc').AsString :=
     FDMemTable2.Lookup('code',
       DataSet.FieldByName('f_code').AsInteger, 'name');
 end;

F4: Können in Indexdefinitionen berechnete Felder verwendet werden?

A: FireDAC unterstützt in der aktuellen Version keine Felder mit "FieldKind = fkCalculated" in Locate, Lookup, IndexFieldNames usw. Verwenden Sie stattdessen fkInternalCalc-Felder.

F5: Wenn ich die Methode FindNearest zur Laufzeit aufrufe, erhalte ich die Fehlermeldung, dass kein aktiver Index vorhanden ist.

A: Der Index muss ausgewählt, nicht nur aktiv sein. Gehen Sie dazu wie folgt vor:

  • Legen Sie "Indexes[i].Selected := True" fest.
  • Oder legen Sie "FDTable1.IndexFieldName := <Name Ihres Index>" fest.

F6: Wie kann ich eine andere Zeichensortierung für die Indizierung von TADDataset definieren?

A: Im Allgemeinen gibt es dafür drei Möglichkeiten:

  • Weisen Sie LCID zu TFDMemTable.Table.Locale zu. FireDAC verwendet CompareStringA und CompareStringW mit dem Flag SORT_STRINGSORT. Die Standardsortierung ist vom DBMS unabhängig. Sie entspricht LOCALE_USER_DEFAULT. Einzelheiten finden Sie in den Win-API-Dokumenten.
  • Ändern Sie den Quellcode für FireDAC.DatS.pas, TFDDatSRow.CompareData, und implementieren Sie einen eigenen Vergleichsalgorithmus.
  • Registrieren Sie eine benutzerdefinierte Funktion bei einer Ausdrucksauswertung. Einzelheiten zur Registrierung finden Sie in FireDAC.Stan.Expr.pas. Dann können Sie diese Funktion bei TFDMemTable.Indexes[..].Expression verwenden. Zum Beispiel: Expression := 'MySort(Name)'.

In einer der nächsten Versionen werden benutzerdefinierte Sortierungen implementiert. Das wird bei SQLite-Treiberfragen, wie der Ihren, hilfreich sein.

F7: Wie kann ich Daten folgendermaßen sortieren: COL1 absteigend, COL2 aufsteigend?

A: IndexFieldNames := 'col_1:D;col_2';

F8: FDQuery.Locate löst für SQL Server "Fehler in Funktionssequenz" aus. Was ist falsch?

A: Es wurde wahrscheinlich FDQuery nach dem expliziten Transaktionsstart geöffnet und dann eine Transaktion übergeben. Und dann wurde FDQuery.Locate aufgerufen, aber es wurden nicht alle Datensätze aus FDQuery abgerufen, sondern Locate hat FetchAll implizit aufgerufen. Deshalb wird dieser Fehler für SQL Server ausgelöst.

Gehen Sie folgendermaßen vor, um diesen Fehler zu vermeiden:

SQL Server macht geöffnete Cursor nach Commit/Rollback ungültig.

F9: Wie werden Nachschlagetabellen am besten implementiert? Offensichtlich sind sie sehr groß, weil das Öffnen/Laden sehr langsam ist.

A: Wenn Sie auf dem Client nicht alle Datensätze benötigen, sollten Sie TFDQuery mit "SELECT ... WHERE ...." verwenden.

F10: Wie kann man bei Nachschlagefeldern die beste Leistung erzielen?

A: Setzen Sie TFDQuery.IndexFieldNames auf LookupKeyFields. FireDAC sucht dann anhand des Client-Index nach Datensätzen in einer Nachschlagedatenmenge.

Wenn die Anzahl der eindeutigen Schlüsselwerte nicht groß ist, setzen Sie LookupCache auf True.

F11: Ich kann nicht anhand des DateTime-Wertes filtern. Was ist falsch?

F: Ich verwende Delphi 2007 mit FireDAC 2.0.11.895 für eine Postgres-Datenbank. Wenn ich versuche, nach einem DateTime-Feld zu filtern, erhalte ich keine genaue Übereinstimmung mit einem folgendermaßen übergebenen Wert:

 created_date = '8/10/2009 14:42:14'           // or even...
 created_date = '8/10/2009 14:42:14.247'     // ... the exact time with millisec

Stattdessen muss ich den DateTime-Wert wie folgt übergeben:

 created_date >= '8/10/2009 14:42:14' AND created_date < '8/10/2009 14:42:15' or
 created_date >= '8/10/2009 14:42:14.000' AND created_date <= '8/10/2009 14:42:14.999'

A: Das Problem liegt daran, dass das DBMS oder die DBMS-API den Zeitwert runden kann. Ein Programmierer erwartet als Dezimalanteil .247, aber es könnte .246 oder etwas anderes sein. Dies ist kein FireDAC-Fehler, sondern die Art und Weise wie ein DBMS arbeitet.

Sie können den Zeitwert auf Sekunden runden und diesen Wert mit einer Konstante ohne den Dezimalanteil vergleichen:

 uses
   FireDAC.Stan.ExprFuncs;
 ...
   FDQuery1.Filter = 'TimeStampDiff(''second'', created_date,
     convert(''timestamp'', ''8/10/2009 14:42:14'')) = 0';