![]() |
Datenbank: SQLite • Version: 3 • Zugriff über: mORMot
Kleine Demo zu mORMot
Liste der Anhänge anzeigen (Anzahl: 2)
So hier mal eine kleine Demo zu
![]() Screenshots spare ich mir mal, denn es geht nicht um die Bilder sondern das ORM Der Kern des Ganzen besteht aus einem Model, welches die Daten-Objekte beinhaltet. Aus diesen Datenobjekten werden dann automatisch die Tabellen erzeugt, bzw. erweitert. In der Demo verwende ich folgendes Datenobjekt:
Delphi-Quellcode:
Aus den published Properties werden die Feldnamen der Tabelle gebildet.
unit Model.Demo.Person;
interface uses SynCommons, SQLite3Commons; type TGeschlecht = ( gsMann, gsFrau ); TSQLPerson = class( TSQLRecord ) private fVorname : SynUnicode; // ist ein Unicode-String fNachname : SynUnicode; // ist ein Unicode-String fGeschlecht : TGeschlecht; // ja, Enums gehen auch function GetAnzeige : string; public property Anzeige : string read GetAnzeige; published property Vorname : SynUnicode read fVorname write fVorname; property Nachname : SynUnicode read fNachname write fNachname; property Geschlecht : TGeschlecht read fGeschlecht write fGeschlecht; end; implementation { TSQLPerson } function TSQLPerson.GetAnzeige : string; begin Result := Nachname + ', ' + Vorname; end; end. Die Tabelle selber bekommt als Namen Person (also TSQL<TabellenName>). Um aus den Daten-Objekten ein Model zu erstellen benutze ich eine eigene Unit, die mir alle Daten-Objekte sammelt und in einem Model zusammenstellt:
Delphi-Quellcode:
Ok, bis hier sollte das alles noch nachvollziehbar sein :)
unit Model.Demo;
interface uses SQLite3Commons; function CreateModel : TSQLModel; implementation uses Model.Demo.Person; function CreateModel : TSQLModel; begin Result := TSQLModel.Create( [TSQLPerson], 'Demo' ); end; end. Jetzt zum schwierigien Teil Client und Server. In der Demo verwende ich einen Http-Server. Also brauchen wir eine VCL-Formular-Anwendung (oder meinetwegen auch eine Service-Anwendung) und setzen diesen Server einmal auf:
Delphi-Quellcode:
ja, das war schon alles ...
uses
mORMot.Connector, mORMot.Connector.Server, Model.Demo; ... fSrvCon := // eine Server-Instanz für TmORMotServerHttp.Create( // einen Http-Server TmORMotConfigurator.Create, // mit der Konfiguration CreateModel // und diesem Model ); Jetzt der passende Client:
Delphi-Quellcode:
Der TmORMotConfigurator kümmert sich um das Erzeugen aller benötigten Objekte.
uses
mORMot.Connector, mORMot.Connector.Client, Model.Demo; ... fCltCon := // eine Client-Instanz TmORMotClientHttp.Create( // für den Zugriff via Http TmORMotConfigurator.Create, // mit der Konfiguration CreateModel // und diesem Model ); Steuern kann man das Verhalten über eine Ini-Datei.
Delphi-Quellcode:
Wird keine Ini-Datei angegeben, dann wird der Name der Ini-Datei aus dem Anwendungsnamen gebildet:
TmORMotConfigurator.Create('<Pfad zur Ini-Datei>');
Code:
Notwendig ist die nicht, da für alle Einstellungen sinnvolle Default-Werte hinterlegt sind.
<MeinAnwendungsName>_mORMot.ini
Um z.B. den Port für den Http-Server einzustellen trägt man folgendes in die Ini-Dateien für Client und Server ein:
Code:
Ist der Server nicht auf dem lokalen Rechner, dann trägt man in der Client-Ini einfach den Hostnamen ein:
[Server]
;Port Default 8080 Port=8888
Code:
Die Konfiguration wird immer nur beim Erzeugen der Connectoren benutzt, somit ist ein Neustart von Server/Client erforderlich.
[Server]
;Host Default localhost Host=<Adresse des Servers> Vielleicht sollte man noch erwähnen dass der Server ein REST-Server ist und die Daten auch direkt via WebBrowser ausgelesen werden können. Sind im Demo-Server schon Datensätze vorhanden, dann einfach mal diesen Link öffnen ![]() (Wer den FireFox einsetzt sollte sich das AddOn JSONview installieren) So das sollte für den ersten Test schon mal reichen :) |
AW: Kleine Demo zu mORMot
In den Sourcen von mORMot ist ein kleiner Bug bzgl. des Lock/UnLock von Records.
In der
Delphi-Quellcode:
muss folgendes angepasst werden
unit SQLite3Commons;
Delphi-Quellcode:
Der Autor ist aber recht fix mit dem Bug-Fixing, somit sollte dieser Fehler kurzfristig in den Original-Quellen behoben sein.
function TSQLRestClientURI.Retrieve(aID: integer; Value: TSQLRecord;
ForUpdate: boolean=false): boolean; var Table: TSQLRecordClass; Resp: RawUTF8; begin result := false; if (self=nil) or (aID<=0) or (Value=nil) then exit; Table := Value.RecordClass; if ForUpdate and not Model.Lock(Table,aID) then exit; // error marking as locked by the client with URIGet(Table,aID,Resp,ForUpdate) do if Lo=200 then begin Value.FillFrom(Resp); Value.fInternalState := Hi; if ForceBlobTransfert then result := RetrieveBlobFields(Value) else result := true; end else // dieser else-Zweig fehlt :o) Model.UnLock(Table,aID); end; ![]() |
AW: Kleine Demo zu mORMot
Der Fehler ist nun auch im Repository behoben
|
AW: Kleine Demo zu mORMot
Liste der Anhänge anzeigen (Anzahl: 3)
Nabend Sir,
Danke für die Demo. Morgen werde ich wohl endlich Zeit dafür haben... Hast Du Erfahrungen, wie die Perfomance mit großen Datenmengen ist (vor allem auch über Netzwerk und im Vergleich zu einer klassischen Datenbankanwendung)? Ich hatte mal früher mit Firebird ein kleines (sehr billiges) Testprojekt erstellt, bei dem man 3 Panels verschieben konnte und diese Verschiebung auch parallel auf einem zweiten "Designer" erfolgte. Das funktioniert auch im Netzwerk, wenn man nicht Firebird embedded nutzt. Siehst Du mal eine Demomöglichkeit mit mORMot... ? |
AW: Kleine Demo zu mORMot
Also zum Thema Geschwindigkeit:
Als Http-Server ist die Performance schon etwas schlechter. Das solltest du mit der beiliegenden Demo sehen können. Dieses liegt aber zum einen am Protokoll und an der AJAX-Kompatibilität (die kann man aber auch abschalten). Man kann aber die Datenbank eben nicht nur per Http, sondern auch z.B. per NamedPipe den Clients zur Verfügung stellen, und das ist dann sehr schnell. Einen direkten Vergleich mit anderen Datenbank-Systemen bzw. Übertragungsprotokollen habe ich noch nicht gemacht. Wäre evtl. auch unfair, da diese ja schließlich nicht die Möglichkeit bieten ein komplexes Business-Objekt einfach so zu verarbeiten. Sollte die Datenbank selber (ist ja ein SQLite3 im Hintergrund) zu langsam sein, so kann man auch eine andere Datenbank (Zugriff muss via OleDB oder ODBC möglich sein) als Basis nehmen. Letztendlich kommt es eben darauf an, was man erreichen möchte: Ich bin gerade dabei eine Datenschnittstelle für MDE-Geräte damit zu bauen. Der Hersteller der MDE-Software bekommt als Vorgabe mit diesem REST-Server seine Daten auszutauschen. Meine Anwendung liest dann von diesem Server die Daten ein. Der Vorteil liegt dabei klar auf der Hand: Mir ist es von nun an egal, was für (MDE-)Geräte da Daten bereitstellen und meine Anwendung kann bleiben wie sie ist, es sei denn auf der Ebene gibt es Gründe für eine Änderung. Mal sehen wie die Hersteller darauf reagieren ... ich gebe da mal ein Feedback ;) ich habe mir mal 2 Methoden zum Speichern und Laden aus deiner Demo-Anwendung rausgepickt und auf mORMot umgeschrieben. Das Model:
Delphi-Quellcode:
die Methode zum speichern:
type
TSQLPanel = class( TSQLRecord ) private fLeft : integer; fTop : integer; published property Left : integer read fLeft write fLeft; property Top : integer read fTop write fTop; end;
Delphi-Quellcode:
die Methode zum laden
procedure TFormTestObjectDB.odbPanel1Click(Sender: TObject);
var odbPanel: TodbPanel; lPanel : TSQLPanel; begin odbPanel := Sender as TodbPanel; lPanel := TSQLPanel.Create; try lPanel.Left := odbPanel.Left; lPanel.Top := odbPanel.Top; lPanel.ID := odbPanel.Tag; fCltCon.Client.Update( lPanel ); finally lPanel.Free; end; end;
Delphi-Quellcode:
es ist aber auch möglich, die Datensätze gleich auf einen Rutsch zu lesen
procedure TFormTestObjectDB.Timer1Timer(Sender: TObject);
var lPanel : TSQLPanel; begin lPanel := TSQLPanel.Create; try if fCltCon.Client.Retrieve( 1, lPanel ) then begin odbPanel1.Left := lPanel.Left; odbPanel1.Top := lPanel.Top; odbPanel4.Left := lPanel.Left; odbPanel4.Top := lPanel.Top; end; if fCltCon.Client.Retrieve( 2, lPanel ) then begin odbPanel2.Left := lPanel.Left; odbPanel2.Top := lPanel.Top; odbPanel5.Left := lPanel.Left; odbPanel5.Top := lPanel.Top; end; if fCltCon.Client.Retrieve( 3, lPanel ) then begin odbPanel3.Left := lPanel.Left; odbPanel3.Top := lPanel.Top; odbPanel6.Left := lPanel.Left; odbPanel6.Top := lPanel.Top; end; finally lPanel.Free; end; end;
Delphi-Quellcode:
oder parametrisiert
fCltCon.FillPrepare( fCltCon.Client, 'ID BETWEEN 1 AND 3' );
Delphi-Quellcode:
dann sieht die Methode so aus:
fCltCon.FillPrepare( fCltCon.Client, 'ID BETWEEN ? AND ?', [], [ 1, 3 ] );
Delphi-Quellcode:
Ein wenig Performance könntest du aber auch dadurch gewinnen, wenn du dir für diese Zugriffe eine TSQLPanel-Instanz vorhältst, dann sparst du dir die Zeit für das ständige Create/Destroy.
procedure TFormTestObjectDB.Timer1Timer(Sender: TObject);
var lPanel : TSQLPanel; op1, op2 : TodbPanel; begin lPanel := TSQLPanel.Create; try if lPanel.FillPrepare( fCltCon.Client, 'ID BETWEEN ? AND ?', [], [ 1, 3 ] ) then while lPanel.FillOne do begin case lPanel.ID of 1 : begin op1 := odbPanel1; op2 := odbPanel4; end; 2 : begin op1 := odbPanel2; op2 := odbPanel5; end; 3 : begin op1 := odbPanel3; op2 := odbPanel6; end; end; op1.Left := lPanel.Left; op1.Top := lPanel.Top; op2.Left := lPanel.Left; op2.Top := lPanel.Top; end; lPanel.FillClose; finally lPanel.Free; end; end; |
AW: Kleine Demo zu mORMot
BTW: Wenn man meine Demo von Http auf NamedPipe umstellen möchte, dann muss man diese Änderungen vornehmen:
Delphi-Quellcode:
// für den Server
fSrvCon := // eine Server-Instanz für // TmORMotServerHttp.Create( // einen Http-Server TmORMotServerNamedPipe.Create( // einen NamedPipe-Server TmORMotConfigurator.Create, // mit der Konfiguration CreateModel // und diesem Model ); // für den Client fCltCon := // eine Client-Instanz // TmORMotClientHttp.Create( // für den Zugriff via Http TmORMotClientNamedPipe.Create( // für den Zugriff via NamedPipe TmORMotConfigurator.Create, // mit der Konfiguration CreateModel // und diesem Model ); |
AW: Kleine Demo zu mORMot
Wenn Du also Dein Datenmodell als Delphi-Objekt ausführst, ist die Bereitstellung eines Rest-Zugriffs auf einen DB-Server dann nur noch ein Einzeiler. Die (Delphi-) Clients können ja trotzdem noch nativ mit dem DB-Server arbeiten. Damit kann man externen Anwendungen Standard-Protokoll-Zugriff auf "seine" Datenbank ermöglichen und hat trotzdem noch exklusive Hoheit über die Geschäftsregeln (ohne umständliche Stored Procedures oder Trigger).
Das ist zwar nicht die Hauptaufgabe von mORMot, aber m.E. ein sehr netter und vor allem schnell realisierter "Seiteneffekt". |
AW: Kleine Demo zu mORMot
Ok, interessant ist das sicher. Zwei Fragen habe ich aber:
Wenn mehrere Clients den Server nutzen, wie werden dann Konflikte gehändelt? Wenn ich eine Datenbank aus Version 1 habe und will die mit einer Programmversion 5 (mit anderer Datenstruktur) benutzen, was passiert dann? Gibt es eine Art Differenzscripte o.ä.? |
AW: Kleine Demo zu mORMot
Wenn du dein Konzept richtig aufsetzt, dann gibt es keine Konflikte (Lock/Unlock)
Und unterschiedliche Versionen Client/Server unterliegen eigentlich den gleichen Bedingungen wie bei einem normalen DB-Server. Die Erweiterung der Tabellenstruktur wird automatisch vom Server auf Basis des Models vorgenommen. Da muss man sich um nichts kümmern. Ebensowenig wie du ein Script mitliefern musst, damit die DB aufgesetzt wird. Problematisch wird es immer dann, wenn du Felder komplett umdeklarierst (z.B. Text->Integer) oder Felder umbenennst. Aber dieses Problem hast du bei jeder Datenbank und ist kein Alleinstellungsmerkmal von mORMot ;) |
AW: Kleine Demo zu mORMot
Hallo,
ich grabe mal diesen Thread hier wieder aus, da ich glaube, dass er ganz gut zum Thema (mORMot in der Praxis) passt. Ich bin gerad in der Situation, dass ich mir Gedanken über die Konzeption/Layout/DB-Design unsere zuküftigen Projekte machen kann. Nach einigem Suchen/Lesen bzgl. N-Tier komme ich immer wieder auf mORMot. Für jemanden der keinerlei Erfahrung mit ORM und Client/Server System hat ist der Anfang doch recht schwer. Besonders bei einer solch gewaltigen Doku (die sich auch noch stündich ändert:) ) Ein kleines Testprojekt habe ich mir mal aufgesetzt. Ich habe ein paar Fragen diesbezüglich wie ihr das System in der Praxis nutzt. 1. Sind eure Formulare eher tabellenbasiert oder zeigt ihr immer nur einen Datensatz an mit der Möglichkeit zu suchen/blättern? 2. Wenn ich eine Tabelle (ich nutze hier Devexpress cxGrid mit eigenem CustomDatasource) anzeige, wie bekomme ich dann z.B. bei einem Artikel (TSQLRecord) den Namen der hinterlegten Artikelgruppe (TSQLRecord). Muss an diesen Stellen wieder mit SQL arbeiten? 3. Macht das interne Rechtesystem Sinn, wenn man wesentlich mehr Rechte braucht? Ich brauche z.B. Rechte auf Objekte (Artikel): Einfügen, Ändern, Löschen, Drucken, Filtern, Suchen, Exportieren, ... Rechte auf Funktionen: Wareneingang buchen, Lieferschein schreiben, Rechnung schreiben, ... mfg Marco |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz