Registriert seit: 1. Mär 2008
Hallo liebe DP-ler,
oft braucht man Objektlisten, die gefiltert, sortiert oder gruppiert werden müssen. Unter Delphi Prism bzw. .net gibt es LINQ, das man in solchen Fällen sicher zu schätzen weiss. Leider gibt es unter Delphi selbst nichts dergleichen. Darum habe ich einmal etwas in diese Richtung erstellt. Aus Zeitgründen sicher noch nicht perfekt, aber es arbeitet soweit zufriedenstellend...
Welche SQL-Befehle werden unterstützt?- SELECT (optional)
- TOP(n) Limitiert die Liste auf die ersten n Objekte
- DISTINCT field Gruppiert die Liste
- CALC(x) Berechnet den Ausdruck x (bsp. Feld1=Feld2*5+(Feld3/2))
- WHERE (x) Filtern (<,>,=,<=,>=, zusätzlich. Upper, Lower, Like (% Wildcard), kombinierbar mit OR; AND; XOR)
- ORDER BY Feld1, Feld2,... Sortierreihenfolge (inkl. ASC/DESC)
- GROUP BY Feld1, Feld2 Gruppiert die Liste (wie distinct)
- UPDATE SET (Feld1=Wert1, Feld2=Wert2) Schreibt neue Werte in die Felder
Zur Funktionsweise:
Die Liste kann Klassen oder Records verwalten. Records haben derzeit die Limitierung, dass in die Werte nicht geschrieben werden kann. Somit funktionieren CALC und UPDATE nicht. Eine Exception wird ausgelöst, wenn versucht wird einen der Befehle in Verbindung mit Records zu nutzen. Enumeration wird unterstützt, daher auch "for in" möglich. Handhabung also wie TList<T>.
Durch den Befehl "Execute()" wird das Kommando abgesetzt und eine neues Objekt als Lookup-Liste zurückgegeben. Löschen von Objekten ist in einer Lookup-Liste nicht möglich.
Zur Berechnung von Werten habe ich eine Calculator Klasse eingebunden. Mit ihr lassen sich einfache Rechenoperationen durchführen und deren Ergebnisse wieder in Properties von Klassen zurückschreiben. Unterstützt werden die Operatoren - + / * ^ ( ) sin cos tan sqr log cot sec csc
Was gilt es zu beachten?- Ausdrücke müssen in Klammer gesetzt werden... zB. where (a=b) and (c=d) oder update set (a=b, c=d)
- Für Delphi 2010 & XE
Neues Update:- UPDATE Befehl um Werte in Properties schreiben zu können
- Parser ein wenig überarbeitet
- Unterstützt Unterklassen
- Der zweite "Where" Ausdruck kann ein Feld sein
- Umbenannt, damit es nicht heisst ich sei anmaßend
- Mit Delphi 2010 getestet
- Records in der Klasse können gelesen werden
Update, Version 1.3, 30.1.2013
Endlich bin ich mit einigen Projekten auf XE3 umgestiegen, daher auch ein Update dieser Klasse.- Kompatibel mit XE3
- Kompatibel mit 64 Bit
- Funktion "Where" hinzugefügt
- Funktion "OrderBy" hinzugefügt
- Funktion "Distinct" hinzugefügt
- Funktion "Move" hinzugefügt
Update, Version 1.4, 15.8.2014
Element Operators- First, gibt das erste Element zurück
- Last, gibt das letzte Element zurück
Custom Sequence Operators- Combine( TEasyLINQ<T> ), kombinieren von zwei Listen (kopiert die Elemente der übergebenen Liste)
Partitioning Operators- Take( n ), gibt die ersten n Elemente zurück
- Skip( n ), überspringt die ersten n Elemente und gibt alle anderen zurück
- Odd, gibt alle Elemente mit ungleicher Position (1,3,5...) zurück
- Even, gibt alle Elemente mit gleicher Position (2,4,6...) zurück
Generation Operators- Range( form, to ), Auswahl eines Bereiches von Elementen
- Repeat( index, n ), Wiederholt das Element mit Index n-mal
Aggregate Operators- Aggregate( field ), berechnet das Produkt aller Element von "field"
- Average( field ), berechnet den Durchschnittswert aller Element von "field"
- Min( field ), gibt den kleinsten Wert aller Element von "field" zurück
- Max( field ), gibt den größten Wert aller Element von "field" zurück
- Sum( field ), berechnet die Summe aller Element von "field"
Update, Version 1.41, 4.9.2014- Bug fix: In GetCMD wurden beim Like Command 6 Zeichen gelöscht, anstatt nur 5
Im Laufe der Zeit wird sich sicher noch die eine oder andere Funktion ergeben. Mit dem Parser bin ich noch nicht so ganz glücklich, hier lässt sich auf jeden Fall noch einiges optimieren. Derzeit müssen Ausdrücke in Klammern gesetzt werden, das vereinfacht das Parsen.
Beispiel:
Delphi-Quellcode:
ClassLinq := TLinq<TMyClass>.Create;
{...}
TempLinq := ClassLinq.Execute( 'ORDER BY LastName, FirstName' );
for item in TempLinq do Memo1.Lines.Add( item.ToString );
TempLinq.Free;
{...}
ClassLinq.Free
Einige SQL-Beispiele aus der beiliegenden Demo:
Delphi-Quellcode:
SELECT WHERE (City="Vienna")
SELECT ORDER BY City,Value
SELECT ORDER BY City,Value DESC
SELECT TOP(3) WHERE (UPPER(Lastname) like "%A%") ORDER BY MySubText.Text
SELECT CALC(value=(value*32+4)/2) ORDER BY value
SELECT TOP(3) WHERE (LOWER(Firstname)="kurt") OR (LOWER(Firstname)="edmund")
SELECT GROUP BY City ORDER BY LastName
SELECT WHERE (MySubText.Text="Sub3") OR (FirstName="Kurt")
UPDATE SET (Firstname="Max", Lastname="Mustermann") WHERE (City="Linz") OR (MySubText.Text="Sub4")
UPDATE SET (Value=CALC(23*2-4)) WHERE (City="Vienna")
Ideen und Wünsche für Erweiterungen und Verbesserungen sind gerne willkommen...
liebe Grüße,
Daniela
Geändert von Daniela.S ( 4. Sep 2014 um 14:00 Uhr)
Grund: Update
|