Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   LINQ ORM Delphi (TMS / Devart) (https://www.delphipraxis.net/199953-linq-orm-delphi-tms-devart.html)

taveuni 5. Mär 2019 07:31

Datenbank: MSSQL • Version: Egal • Zugriff über: LINQ

LINQ ORM Delphi (TMS / Devart)
 
Hallo zusammen,

In Kürze beginnen wir ein grösseres Projekt welches in Delphi umgesetzt werden muss. Von Visualstudio .Net bin ich mir mittlerweile einige Annehmlichkeiten gewohnt. Wie z.B. das SQL Gefrickel im Code zu vermeiden. Frage: Hat jemand Erfahrung mit einem ORM wie Devart, TMS Aurelius oder anderen und kann eine Empfehlung abgeben?

Union 5. Mär 2019 11:18

AW: LINQ ORM Delphi (TMS / Devart)
 
Ich arbeite seit ein paar Jahren mit Aurelius. Erspart einem eine Menge SQL Gefummel und hilft so Fehler zu vermeiden. Allerdings sind die Datenmengen die da geschaufelt werden in der realen Welt nicht unerheblich. Dann muss man mit spezifischen Modellen arbeiten oder doch wieder manuell mit SQL arbeiten.

haentschman 5. Mär 2019 11:44

AW: LINQ ORM Delphi (TMS / Devart)
 
Hallöle...
Zitat:

Wie z.B. das SQL Gefrickel im Code zu vermeiden
Dazu braucht es nicht umbedingt ein ORM. Ich verwende eine andere Strategie. Es gibt für jedes DBMS was benutzt wird, ein Interface. Der komplette Zugang zur DB ist in diesem Interface gekapselt. Im Interface werden dann die Ergebnisse der SQL Abfragen in Objekte gewandelt. Die Anwendung kennt eigentlich keine Datenbank. Die Daten könnten auch aus Oma´s Küchenschrank kommen. Dann sage ich nur in der Anwendung (Aufruf procedure im Interface)... "Fülle mir mal die Liste mit den Mitarbeitern". Am Ende habe ich eine TObjectList<TMitarbeiter>...fertsch. Nachteil: Man verzichtet hoffentlich auf datensensitive Controls...denn da funktioniert das nicht. :stupid:
Zum SQL Gefrickel:
[Meine Lösung]
Meine Statements liegen in einer Ordnerstruktur. Das bedeutet, die Statements sind ausführbar im Editor. Diese Struktur wird als Ressource einkompiliert. Das Interface holt sich die SQL aus der Ressource entsprechend des DBMS. In den Proceduren gibt es nur den Namensaufruf und die Zuordnung der Parameter...fertsch
Delphi-Quellcode:
function TBlubbDatabase.GetSQLByName(SQLName: string): string;
var
  SQLStream: TResourceStream;
  SQLStrings: TStringList;
  SQLStringsDecrypt: TStringList;
begin
  Result := '';
  SQLStrings := TStringList.Create;
  try
    SQLStringsDecrypt := TStringList.Create;
    try
      SQLStream := TResourceStream.Create(HInstance, SQLName, PWideChar(conDatabaseResourceGroupString));
      try
        try
          SQLStrings.LoadFromStream(SQLStream);
          SQLStringsDecrypt.Text := TBlubbToolsCrypt.Decrypt(SQLStrings.Text, conKey); //Verschlüsselung wenn nötig
          SQLStringsDecrypt.Delete(0); // Kommentar entfernen
          Result := SQLStringsDecrypt.Text;
        except
          Result := '';
        end;
      finally
        SQLStream.Free;
      end;
    finally
      SQLStringsDecrypt.Free;
    end;
  finally
    SQLStrings.Free;
  end;
end;
Delphi-Quellcode:
procedure TBlubbDatabase.FillList(List: TBlubbFieldList; TableName: string);
var
  I: Integer;
  Qry: TFDQuery;
  Field: TBlubbField;
begin
  Qry := CreateQuery;
  try
    Qry.SQL.Text := Format(GetSQLByName('BLUBB_TABLE_FIELDLIST'), [TableName]);
    Qry.Open;
    if not Qry.Eof then
    begin
      List.Clear;
      for I := 0 to Qry.Fields.Count - 1 do
      begin
        Field := TBlubbField.Create;
        Field.FieldIndex := I;
        Field.FieldName := Qry.Fields[I].FieldName;
        Field.Fieldype := Qry.Fields[I].DataType;
        List.Add(Field);
      end;
    end;
  finally
    Qry.Free;
  end;
end;

taveuni 5. Mär 2019 13:01

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Union (Beitrag 1426976)
Ich arbeite seit ein paar Jahren mit Aurelius. Erspart einem eine Menge SQL Gefummel und hilft so Fehler zu vermeiden. Allerdings sind die Datenmengen die da geschaufelt werden in der realen Welt nicht unerheblich. Dann muss man mit spezifischen Modellen arbeiten oder doch wieder manuell mit SQL arbeiten.

Wie meinst Du das? Bezüglich Performance?

taveuni 5. Mär 2019 13:06

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von haentschman (Beitrag 1426979)
(..)Ich verwende eine andere Strategie.(..)

Ja. Das habe ich auch gemacht in früheren Delphi Projekten. Wenn Du aber ein paar Jahre mit EntityFrameworks wie in .Net Visualstudio enthalten gearbeitet hast....
Es kann so einfach sein. Code First oder Database First. Und dann alles per LINQ. Ist schon eine andere Nummer bezüglich Übersichtlichkeit und Anwendung.

Schokohase 5. Mär 2019 13:19

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von taveuni (Beitrag 1426986)
Zitat:

Zitat von Union (Beitrag 1426976)
Ich arbeite seit ein paar Jahren mit Aurelius. Erspart einem eine Menge SQL Gefummel und hilft so Fehler zu vermeiden. Allerdings sind die Datenmengen die da geschaufelt werden in der realen Welt nicht unerheblich. Dann muss man mit spezifischen Modellen arbeiten oder doch wieder manuell mit SQL arbeiten.

Wie meinst Du das? Bezüglich Performance?

Ja, es gibt bei .Net auch eine Vielzahl die EF eher meiden und z.B. Dapper verwenden, weil man hier noch Einfluß auf den SQL-Code hat (Performance).

Zitat:

Zitat von taveuni (Beitrag 1426987)
Zitat:

Zitat von haentschman (Beitrag 1426979)
(..)Ich verwende eine andere Strategie.(..)

Ja. Das habe ich auch gemacht in früheren Delphi Projekten. Wenn Du aber ein paar Jahre mit EntityFrameworks wie in .Net Visualstudio enthalten gearbeitet hast....
Es kann so einfach sein. Code First oder Database First. Und dann alles per LINQ. Ist schon eine andere Nummer bezüglich Übersichtlichkeit und Anwendung.

Kann es sein, dass du diese Entity-Modelle auch im Business-Layer verwendest? Das wäre bei mir ein NoGo, denn die gehören ausschließlich dem Persistence-Layer

MyRealName 5. Mär 2019 13:33

AW: LINQ ORM Delphi (TMS / Devart)
 
Beim Aurelius musst Du aufpassen, ob Du datenbank transaktionen brauchst. Das hat da kein gutes Modell. Ich hatte eine längere Diskussion mit Wagner Landgraf (dem Programmierer von Aurelius) und hab ihm erklärt dass sein augenblickliches Modell es nicht zulässt, 2 Instanzen vom gleichen Object zu erstellen, jedes mit eigenem ObjectManager und dann getrennt commit oder rollback zu machen. Bei Aurelius (Stand Version 3.3) ist es so, dass es global nur eine Transaction gibt (ich nutze UniDAC), die von der TUniConnection selbst kommt. Das heisst dann aber auch, dass wenn ich Commit in einem Fenster mache, er auch die Daten von Fenster 2 committed.

Seine Lösung war eine neue DbVerbindung für jedes Fenser. :roll:

Also ein kleieres Projekt machte ich damit, das geht sehr gut, dort nutze ich aber nur sehr begrenzt und sequentiell das Schreiben der Daten in die Db.

sakura 5. Mär 2019 14:10

AW: LINQ ORM Delphi (TMS / Devart)
 
Um mal noch ein interessantes Projekt zu nennen: mORMot - Super Doku, allerdings eine gewissen Einarbeitungszeit ist schon nötig.

...:cat:...

mkinzler 5. Mär 2019 14:14

AW: LINQ ORM Delphi (TMS / Devart)
 
Oder MarshMallow (nun Teil von Spring4D).

Union 5. Mär 2019 14:15

AW: LINQ ORM Delphi (TMS / Devart)
 
Ja, mOrmot hat eine steile Lernkurve. Dafür ist es aber auch wirklich umfassend. Leider läuft auch die interne Kommunikation C/S mit JSON. Daher eher für echte Multi-Tier Anwendungen geeignet. Vorteil: Es ist zu jeder Delphi-Version kompatibel. Nachteil: Es ist zu jeder Delphi-Version kompatibel.
Basiert daher zwingend auf Vererbung und eigenen Datentypen.

Schokohase 5. Mär 2019 14:16

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von MyRealName (Beitrag 1426989)
Seine Lösung war eine neue DbVerbindung für jedes Fenser. :roll:

Die richtige Lösung heißt eigentlich pro ObjectManager eine eigene DbVerbindung und für jeden Kontext einen eigenen ObjectManager

sakura 5. Mär 2019 14:54

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Union (Beitrag 1426994)
Leider läuft auch die interne Kommunikation C/S mit JSON. Daher eher für echte Multi-Tier Anwendungen geeignet.

Wieso sollte das nicht gehen? Wir nutzen es genau so, mit hunderten Clients ohne Probleme.

...:cat:...

MyRealName 5. Mär 2019 19:25

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Schokohase (Beitrag 1426997)
Zitat:

Zitat von MyRealName (Beitrag 1426989)
Seine Lösung war eine neue DbVerbindung für jedes Fenser. :roll:

Die richtige Lösung heißt eigentlich pro ObjectManager eine eigene DbVerbindung und für jeden Kontext einen eigenen ObjectManager

Naja, jedes Fenster hatte in meinem Beispiel innerhalb dieser Diskussion einen eigenen ObjectManager. Aber da es eine MDI Anwendung ist im Netz, die von jedem Fenstertyp soviele Instanzen erstellen kann wie man wll, ist dies keien akzeptale Lösung, IMHO, da dies zu hunderten von Verbindungen führt. Besser wäre eine Transaction-Lösung, wo man eine DbVerbindung hat und jeder ObjectManager eine eigene Transaction besitzt.

Schokohase 5. Mär 2019 20:11

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von MyRealName (Beitrag 1427011)
Zitat:

Zitat von Schokohase (Beitrag 1426997)
Zitat:

Zitat von MyRealName (Beitrag 1426989)
Seine Lösung war eine neue DbVerbindung für jedes Fenser. :roll:

Die richtige Lösung heißt eigentlich pro ObjectManager eine eigene DbVerbindung und für jeden Kontext einen eigenen ObjectManager

Naja, jedes Fenster hatte in meinem Beispiel innerhalb dieser Diskussion einen eigenen ObjectManager. Aber da es eine MDI Anwendung ist im Netz, die von jedem Fenstertyp soviele Instanzen erstellen kann wie man wll, ist dies keien akzeptale Lösung, IMHO, da dies zu hunderten von Verbindungen führt. Besser wäre eine Transaction-Lösung, wo man eine DbVerbindung hat und jeder ObjectManager eine eigene Transaction besitzt.

Du hast da ein grundlegendes Problem im Design. Wenn du das Konzept umstellst, dann verschwinden auch deine Probleme.

- Daten holen:

ObjectManager nach EntityObject/en fragen.
Aus den EntityObject/en das BusinessObject erzeugen
ObjectManager wegwerfen.
Mit dem BusinessObject arbeiten.

- Daten schreiben:

ObjectManager nach EntityObject/en fragen.
EntityObject/e mit BusinessObject aktualisieren
ObjectManager Änderungen speichern
ObjectManager wegwerfen.

Jetzt mal so nachzählen: Wieviele ObjectManager haben wir so bei 50 MDI-Formularen geöffnet? IdR 0 (in Worten null) nur wenn etwas geladen oder gespeichert wird, dann sind die da und weil es für jede Aktion Lesen oder Schreiben einen eigenen ObjectManager gibt, kommen die sich auch nicht mit den Transaktionen ins Gehege.

MyRealName 5. Mär 2019 21:33

AW: LINQ ORM Delphi (TMS / Devart)
 
Das problem ist ja aber, dass ich nicht eine komplett neue Anwendung schreibe, sondern schon 700.000 Zeilen Code habe ;) Und das ist alles basierend auf einem transaktionellen modell, wo die einzelnen Fenstern in einer eigenen Transaktion laufen.

Das umzubauen ist auch ziemlich heftig :p

Schokohase 5. Mär 2019 22:04

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von MyRealName (Beitrag 1427016)
Und das ist alles basierend auf einem transaktionellen modell, wo die einzelnen Fenstern in einer eigenen Transaktion laufen.

Das umzubauen ist auch ziemlich heftig :p

Das war aber so noch nie richtig, denn eine Transaktion sollte immer nur so lang wie nötig bestehen. Dieser Zeitraum liegt in der Praxis im Sekunden- oder sogar Millisekundenbereich.

Es ist allerdings etwas unfair wenn du hier die Schuld auf Aurelius schiebst, denn so hört sich deine Aussage dazu an.

MyRealName 6. Mär 2019 13:27

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Schokohase (Beitrag 1427017)

Das war aber so noch nie richtig, denn eine Transaktion sollte immer nur so lang wie nötig bestehen. Dieser Zeitraum liegt in der Praxis im Sekunden- oder sogar Millisekundenbereich.

Das kann man nicht so pauschal sagen. Nimmt man den traditionellen Delphi Anatz, dann hat man TTable/TQuery Komponenten, die über ein TDataSource mit visuellen Komponenten verbunden sind.
Ist man da mit einer Interbase/Firebird Datenbank verbunden, geht es garnicht andrs als dass man über einen langen Zeitraum die Transaktion offen hat, denn sowie man sie schliesst, schliessen die Table/Queries auch.

Zitat:

Zitat von Schokohase (Beitrag 1427017)
Es ist allerdings etwas unfair wenn du hier die Schuld auf Aurelius schiebst, denn so hört sich deine Aussage dazu an.

Da hast Du eventuell recht, ich muss da mal drüber nachdenken, da dieses Modell ja keine aktive Transaktion braucht, es lädt ja alles in Object Listen.
Nichts desto trotz besteht die Gefahr die Kritik dass es nicht sauber gekapselt ist und man unter Umständen Sachen committed, die man noch garnicht schreiben will.

Schokohase 6. Mär 2019 13:41

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von MyRealName (Beitrag 1427072)
Zitat:

Zitat von Schokohase (Beitrag 1427017)

Das war aber so noch nie richtig, denn eine Transaktion sollte immer nur so lang wie nötig bestehen. Dieser Zeitraum liegt in der Praxis im Sekunden- oder sogar Millisekundenbereich.

Das kann man nicht so pauschal sagen. Nimmt man den traditionellen Delphi Anatz, dann hat man TTable/TQuery Komponenten, die über ein TDataSource mit visuellen Komponenten verbunden sind.
Ist man da mit einer Interbase/Firebird Datenbank verbunden, geht es garnicht andrs als dass man über einen langen Zeitraum die Transaktion offen hat, denn sowie man sie schliesst, schliessen die Table/Queries auch.

Doch kann man so pauschal sagen.
Zitat:

Ziel eines Transaktionssystems ist es stets, möglichst viele Transaktionen in möglichst kurzer Zeit abzuwickeln.
Quelle

Nur weil Emba das mit dem Rapid Application Development da etwas losgetreten hat, wird es nicht richtig. Man kann damit schnell mal was hinklatschen, aber dadurch hast du auch schon die Trennung zwischen UI, Logik und Persistenz nicht eingehalten. Also gleich mehrere Fehler auf einmal.

Die Rache kommt irgendwann später, aber sie kommt.

Natürlich funktioniert so ein Ansatz, aber er klebt halt wie Pech an deinen Händen.

MyRealName 6. Mär 2019 15:47

AW: LINQ ORM Delphi (TMS / Devart)
 
Da kommen wir wieder zu dem zurück, wo ich sagte, dass die Anwendung ja schon da ist, schon seit Delphi 2 und ich bezweifle, das diese ORM Modelle damals schon gang und gäbe waren.

Nichts desto trotz sehe ich den ObjectManager eigentlich als meine Datenhalter an, der sich drum kümmert, meine aus der Datenbank geladenen Daten im Speicher zu halten.
Es würde ja auch nicht viel Sinn machen wenn :

Aurelius lädt Daten aus der DB
diese werden in Entities abgelegt
Ich lade die Entities dann in eigene Objecte, damt ich den ObjectManager freigeben kann
Ich arbeite dann mit meinen Objekten
und wenn ich Änderungen schreiben will, lade ich wieder die Entities aus der DB, ändere sie und schreibe sie zurück.

Da ist für mich 1 Kappe zuviel.
Die Entities sind ja direkt mit deiner GUI verbindbar und werden auf zuruf erst in die DB geschrieben (ObjectManager.Flush;). Solange ich dies nicht aufrufe sollte es möglich sein, an den objekten rumzufummeln, bis ich schwarz werde, oder ?

Schokohase 6. Mär 2019 16:29

AW: LINQ ORM Delphi (TMS / Devart)
 
@MyRealName

Doch, genau so macht man das mit den Entitäten. Denn diese Entitäten sind die Datenbank-Tabellen als Klassen dargestellt. Und mit der Tabellen-Struktur löst man das Problem der Speicherung. Punkt.

Das Business-Objekt kann dabei schon wieder ganz anders aussehen.

Kleines Beispiel:

Wir haben einen Blog-Eintrag und jeder Benutzer diesen Beitrag bewerten.

Das Business-Objekt sieht so aus
Code:
BlogEntry
- Id
- Titel
- Body
- Rate (Bewertung des Benutzers)
Die Entity-Objekte (Tabellen) dazu sehen aber etwas anders aus
Code:
Blog
- Id
- Titel
- Body

BlogUserRate
- BlogId
- UserId
- Rate
denn wir wollen in den Tabellen die Bewertung von n Benutzern speichern können.

Wenn einem da also auch nichts auf die Füße fallen soll, dann trennt man ganz brav zwischen Business-Layer und Daten-Layer.

Zitat:

Zitat von MyRealName (Beitrag 1427096)
Da kommen wir wieder zu dem zurück, wo ich sagte, dass die Anwendung ja schon da ist, schon seit Delphi 2 und ich bezweifle, das diese ORM Modelle damals schon gang und gäbe waren.

Das mag schon sein, aber die Zeit der Holzräder und Kutschen ist auch gottlob vorbei und wir wünschen uns diese Zeit des Reisens auch nicht mehr zurück. Wir haben da jetzt etwas Besseres (Luftreifen und Luftfederung).

MyRealName 6. Mär 2019 17:00

AW: LINQ ORM Delphi (TMS / Devart)
 
Aber dein Modell ha ja auch nur 3 layer :

1. Datenbank mit Tabellen
2. Entities, die die Daten halten
3. GUI

Was du aber vorher geschrieben hast (zumindest wie ich es verstehe) war :

1. Datenbank
2. Entities
3. Meine Business Logic Objekte
4. GUI

Welches ist es denn ?

Stevie 7. Mär 2019 16:28

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von mkinzler (Beitrag 1426993)
Oder MarshMallow (nun Teil von Spring4D).

Würd ich nur bedingt zu raten, da ich Entwicklung dieses Teils erstmal auf Eis lege.

WiPhi 12. Mär 2019 16:06

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Stevie (Beitrag 1427250)
Würd ich nur bedingt zu raten, da ich Entwicklung dieses Teils erstmal auf Eis lege.

Könnte man dann nicht das Spring.Nullable aus der großen Spring-Unit in eine eigene Unit verlagern, um Konflike mit ORM Nullables (wie Aurelius) zu vermeiden? s. https://www.delphipraxis.net/199250-...-nullable.html

Generell finde ich aber, dass man die beiden Frameworks sehr gut miteinander kombinieren kann. :thumb: Bis jetzt war das größte Problem nur das Nullable.

mkinzler 12. Mär 2019 16:12

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Stevie (Beitrag 1427250)
Zitat:

Zitat von mkinzler (Beitrag 1426993)
Oder MarshMallow (nun Teil von Spring4D).

Würd ich nur bedingt zu raten, da ich Entwicklung dieses Teils erstmal auf Eis lege.

Schade

Schokohase 12. Mär 2019 16:54

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von MyRealName (Beitrag 1427108)
Aber dein Modell ha ja auch nur 3 layer :

1. Datenbank mit Tabellen
2. Entities, die die Daten halten
3. GUI

Was du aber vorher geschrieben hast (zumindest wie ich es verstehe) war :

1. Datenbank
2. Entities
3. Meine Business Logic Objekte
4. GUI

Welches ist es denn ?

Ich habe 3 Layer
  1. UI-Layer
  2. Business-Layer
    • Business-Objekte
  3. Persistenz-Layer
    • Entity-Objekte
    • Datenbank-Methoden
Merke: Nicht jede Klasse macht einen Layer, sondern ein Layer besteht aus mehreren Klassen (siehe UI, die aus vielen Controls besteht).

taveuni 13. Mär 2019 06:47

AW: LINQ ORM Delphi (TMS / Devart)
 
Zitat:

Zitat von Schokohase (Beitrag 1427565)

Ich habe 3 Layer
  1. UI-Layer
  2. Business-Layer
    • Business-Objekte
  3. Persistenz-Layer
    • Entity-Objekte
    • Datenbank-Methoden
Merke: Nicht jede Klasse macht einen Layer, sondern ein Layer besteht aus mehreren Klassen (siehe UI, die aus vielen Controls besteht).

Was verwendest Du denn für ein Framework?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:56 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