AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte EasyLINQ, eine generische Liste die einfache SQL Befehle ausführt
Thema durchsuchen
Ansicht
Themen-Optionen

EasyLINQ, eine generische Liste die einfache SQL Befehle ausführt

Ein Thema von Daniela.S · begonnen am 6. Sep 2011 · letzter Beitrag vom 4. Sep 2014
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Daniela.S
Daniela.S
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
Angehängte Dateien
Dateityp: zip EasyLinq.zip (150,1 KB, 49x aufgerufen)
Dateityp: zip EasyLinq1.3.zip (198,9 KB, 32x aufgerufen)
Dateityp: zip EasyLINQ1.4.zip (22,7 KB, 14x aufgerufen)
Dateityp: zip EasyLINQ1.41.zip (22,7 KB, 20x aufgerufen)

Geändert von Daniela.S ( 4. Sep 2014 um 14:00 Uhr) Grund: Update
 
Benutzerbild von Phoenix
Phoenix
 
#11
  Alt 6. Sep 2011, 22:17
Barry schrieb schon an einigen Stellen, welche Probleme sie mit Lambdas aktuell haben, z.B. hier.
Naja, "aktuell" ist relativ. Das Post war von 2008
Aber es stimmt: Für vollständige Type Inference braucht man einen Multipass Compiler, und Delphi ist historisch nunmal ein Single-Pass Compiler (was nicht heisst, dass der Compiler zwangsläufig alles mehrfach durchgehen muss, aber an manchen Stellen ist das eben nötig).
Sebastian Gingter
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

 
Delphi 10.1 Berlin Enterprise
 
#12
  Alt 6. Sep 2011, 22:36
Barry schrieb schon an einigen Stellen, welche Probleme sie mit Lambdas aktuell haben, z.B. hier.
Naja, "aktuell" ist relativ. Das Post war von 2008
Aber es stimmt: Für vollständige Type Inference braucht man einen Multipass Compiler, und Delphi ist historisch nunmal ein Single-Pass Compiler (was nicht heisst, dass der Compiler zwangsläufig alles mehrfach durchgehen muss, aber an manchen Stellen ist das eben nötig).
Ich schrieb nicht, dass der Post aktuell ist, sondern das Problem, und da sich in der Hinsicht nix getan hat, isses immernoch aktuell
Stefan
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

 
Delphi XE4 Enterprise
 
#13
  Alt 12. Sep 2011, 13:31
Neues Update...

- Parser überarbeitet
- Update Befehl hinzugefügt
- Unterklassen werden unterstützt

Geändert von Daniela.S (12. Sep 2011 um 13:52 Uhr)
  Mit Zitat antworten Zitat
Elvis

 
Delphi 2010 Professional
 
#14
  Alt 12. Sep 2011, 16:05
Mein Delphi 2010 stoplert über 2 Sachen:

In Calculator.Calulate benutzt du eine (scheinend globale?) Variable namens FormatSettings.
Die gibt es bei mir nicht.
Ich habe es so gelöst.
Delphi-Quellcode:
  FormatSettings : TFormatSettings;
begin
  fValid := True;
  if Length( s ) <3 then begin
    fValid := False;
    Exit( 0 );
    end;

  SysUtils.GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FormatSettings);
Der Call füür getlocale ist sicherlich weniger teuer, als sowas statisch für die Laufzeit der App zu cachen. (Da du ja dann keine Änderungen der Settings bemerken würdest)


Dann benutzt du an 2 Stellen einen Safecast ("as") auf TObject, den mag mein Delphi auch nicht.
Ich musst hier einen Hard-Cast machen:
Delphi-Quellcode:
//TLinQ<T>.Remove
TObject(fItems[index]).Free;
//TLinQ<T>.Clear;
    for item in fItems do TObject(item).Free;
Da du in beiden Fällen vorher die RTTI fragst, ob T eine Klasse ist, musst du hier auch nicht befürchten, dass du den Kater auf TEichhörnchen wurschtelst...

Rein vom API-Design her, finde ich es ein wenig zu einvernehmend die Unit LinQ und die Klasse TLinq zu nennen.
Solche doch sehr offensichtlichen Namen sollten dem Delphi-Team vorbehalten bleiben.
Falls Delphi irgendwann sowas kriegt, könnten Unit- oder Type-Name mit dem kollidieren, was Borlemb aus dem Hut zaubert.
Oder es kollidiert mit den sicherlich vorhandenen anderen LinQ-Workarounds für Delphi.
Oh, und "SELECT" als Prefix ist anscheinend gar nicht nötig. Vllt einfach aus den Beispielen rausnehmen.
Wirkt komisch, wenn man keine Property-liste angeben kann.

Ansonsten ist das sicherlich eine nette Bereicherung für so manchen.
Robert Giesecke
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

 
Delphi XE4 Enterprise
 
#15
  Alt 12. Sep 2011, 17:20
Wie schon geschrieben habe ich es noch nicht auf Delphi 2010 probiert. Derzeit verwende ich die Unit in einem XE Projekt. Aber ich stürze mich gleich nachher darauf

FormatSettings gibt es erst ab Delphi XE. Beinhaltet von da an den DecimalSeparator.

Am Namen wird es nicht liegen, kann ich gerne ändern. Ich bezweifle jedoch dass Linq in absehbarer Zukunft erscheinen wird. Es wurde 2005 schon mal angekündigt. Was hat sich getan? Nix Nichtmal auf Roadmaps konnte ich das bisher erblicken. Solange Lambda, Extension Methods und Type Inference per Default nicht in irgendeiner Art implementiert sind, steht auch die grundlegende Technik dahinter nicht zur Verfügung. Bei XE2 muss ich erst schauen was sich in diesem Bereich getan hat.

Großes Problem ist auch, dass es bei Generics in Delphi 2010 sehr viele Fehler gab. XE hat mir hier auch schon einige Interne Fehler geworfen. XE2 ist da schon um einiges besser.

Und die Rtti funktioniert mit Records scheinbar immer noch nicht.

Tante Edit sagt: Achja, Select ist Optional, kann man um der Syntax-Willen schreiben...
  Mit Zitat antworten Zitat
Elvis

 
Delphi 2010 Professional
 
#16
  Alt 12. Sep 2011, 17:37
Wie schon geschrieben habe ich es noch nicht auf Delphi 2010 probiert. Derzeit verwende ich die Unit in einem XE Projekt. Aber ich stürze mich gleich nachher darauf

FormatSettings gibt es erst ab Delphi XE. Beinhaltet von da an den DecimalSeparator.
Ist das eine Funktion oder eine globale Variable?
Letzteres wäre schon ganz schön Kac*e und sollte den Borlembern um die Ohren geworfen werden.
Aber wenn ich FormatSettings als lokale Variable nehme und in Calculate mit der Änderung oben besetze fluppt es.

Zitat:
Und die Rtti funktioniert mit Records scheinbar immer noch nicht.
Dein Bleistift läuft bei D2010 nach meinen Änderungen, wenn man Record auswählt.
Robert Giesecke
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

 
Delphi 12 Athens
 
#17
  Alt 12. Sep 2011, 17:42
Ist das eine Funktion oder eine globale Variable?
Letzteres wäre schon ganz schön Kac*e und sollte den Borlembern um die Ohren geworfen werden.
Es ist eine globale Variable! Damit es abwärtskompatibel bleibt, ging es wohl auch nicht anders. Faktisch zeigt FormatSettings.DecimalSeparator und DecimalSeparator so auf denselben Speicherbereich. Ändere ich das eine, ändert sich auch das andere (wäre sonst auch tödlich).

Grundsätzlich sollte man aber immer ein eigenes FormatSettings kreieren, dann klappts auch mit dem Multithreading.
Uwe Raabe
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

 
Delphi XE4 Enterprise
 
#18
  Alt 12. Sep 2011, 17:43
Man kann (oder zumindest habe ich es bis jetzt noch nicht geschafft) in Records zu schreiben. GetValue legt immer eine neue Kopie an. Auch mit TValue.MakeWithoutCopy funktioniert es nicht. Bislang habe ich im Internet auch keine Informationen gefunden woran es liegt.

Ja FormatSettings ist Global. Ein Record das auch verschiedene Funktionen zur Verfügung stellt. Soweit ich gesehen habe kein SingleTon und auch nicht Threadsicher.

Ich lade gleich das Update hoch... eine Minute noch...
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

 
Delphi XE4 Enterprise
 
#19
  Alt 12. Sep 2011, 17:55
Update ist Online
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

 
Delphi 12 Athens
 
#20
  Alt 12. Sep 2011, 17:56
Das waren aber 12 Minuten
Detlef
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      

 

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 06:14 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