Delphi ORM SOA MVC SQL NoSQL JSON REST mORMot

  • View
    1.666

  • Download
    19

  • Category

    Software

Preview:

DESCRIPTION

Slides published for BeDelphi 2014 Event. Create high performance Client Server ORM SOA REST MVC applications using Open Source Synopse mORMot framework and Delphi. Publish any SQL or NoSQL database content over JSON or XML: SQLite3, PostgreSQL, Oracle, MSSQL, FireBird, MongoDB. Define RESTful services using interfaces. Create MVC web applications, using Mustache templates. Running under Windows or Linux, with VCL/FMX clients on Mac OSX, Android or iOS/iPhone/iPad, or AJAX/PhoneGap.

Citation preview

mORMot & Friends

Arnaud Bouchez

Opinions Ahead

Great times for us

Great times for us

Delphi is Hype

Delphi + Pascal > Ruby

If you say Delphi is dead,

YOU are dead!

Two Languages In One

Application Language

like Java C#

System Language

like C C++

Dual Memory Management

Automatic Memory Management

COW and refcount

Manual Memory Management

Uses much less CPU/RAM

Server stability

Dual Memory Management

Automatic Memory Management

COW and refcount

Manual Memory Management

Uses much less CPU/RAM

Server stability

ARC?

New opportunities

New platforms

New compilers

Great communities

Third parties

Open Source

Unleash your power

Decades of experience

Business knowledge

Productive tools

Unleash your power

Decades of experience

Business knowledge

Productive tools

Innovative concepts

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

Open Source

Started in 2008

3520 checkins since 2010

56 COCOMO years

Open Source

Started in 2008

3520 checkins since 2010

56 COCOMO years

http://synopse.info/fossil

http://github.com/synopse/mORMot

http://openhub.net/p/mormot

LOC

Code 213,000

Comments 50,000

Blanks 21,000

Total 284,000

http://synopse.info/fossil

http://github.com/synopse/mORMot

http://openhub.net/p/mormot

Doc as Specs

Exhaustive

Maintained

Open Source

http://synopse.info/files/html

1800 pages of pdf

SynProject powered

Test Driven

17,599,266 tests

Write the test

Fail the test

Write the implementation

Pass the test

Test Driven

17,599,266 tests

Regression

Performance

Thread safety

Cross platform – Cross compiler

http://synopse.info/forum

Feedback and support

Topics 2,200

Posts 13,500

Registered users 1,100

Hall of fame Alexander (sha)

Alfred Glaenzer (alf)

Arnaud Bouchez

Aweste

Cheemeng

CoMPi

Damien (ddemars)

David Mead (MDW)

Delphinium

DigDiver

EMartin

Eric Grange

Esmond

Joe (jokusoft)

Jordi Tudela

Mario Moretti

Martin Suer

MChaos

Ondrej (reddwarf)

Pavel (mpv)

Pierre le Riche

RalfS

Sabbiolina

Sanyin

Sinisa (sinisav)

Sllimr7139

Vadim Orel

Win2014

Wolfgang Ehrhardt (via MPL)

Hall of fame Alexander (sha)

Alfred Glaenzer (alf)

Arnaud Bouchez

Aweste

Cheemeng

CoMPi

Damien (ddemars)

David Mead (MDW)

Delphinium

DigDiver

EMartin

Eric Grange

Esmond

Joe (jokusoft)

Jordi Tudela

Mario Moretti

Martin Suer

MChaos

Ondrej (reddwarf)

Pavel (mpv)

Pierre le Riche

RalfS

Sabbiolina

Sanyin

Sinisa (sinisav)

Sllimr7139

Vadim Orel

Win2014

Wolfgang Ehrhardt (via MPL)

… YOU ?

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

Architecture Switch

BBM → Clean

nTier → SOA

SOAP → REST

RAD → MVC/MVVM

SQL → ORM

NoSQL → ODM

OOP → SOLID

BBM → Clean

Architecture?

BBM

Clean & Agile

Architecture

Premature architecture

may be the root of all evil

Not looking at the big picture

is WORSE

Prevalent Architecture

Big Ball Of Mud

Customer Focused

Pragmatic Agile

nTier → SOA

Multi-Tier

SOA

Multi-Tier

Three-tier architecture

Multi-Tier

Four-tier architecture

Multi-Tier

Logical vs Physical

Multi-Tier

Logical vs Physical

Service-Oriented Architecture (SOA)

Service-Oriented Architecture (SOA)

Flexible set

of design principles

Inter-operable

producer/consumer services

Service-Oriented Architecture (SOA)

Inter-operable

producer/consumer services

Service-Oriented Architecture (SOA)

Service Composition

Service-Oriented Architecture (SOA)

Loosely coupled

systems and domains

Mostly stateless

MicroServices

Service-Oriented Architecture (SOA)

Implementation Independence

Platform

Location

Availability

Versions

SOAP → REST

SOAP

REST

SOAP

Simple Object Access Protocol

XML WSDL

Standard

Proven

SOAP

Simple? Object Access Protocol

XML WSDL

Standard?

Proven

REST

REST

Brother of HTTP

Same Father, Roy Fielding

REST

Brother of HTTP

Resource based

Using identifiers

Uniform interface

Transmission by representation

Stateless

REST

Brother of HTTP

http://www.mysite.com/pictures/logo.png Image Resource

REST

Brother of HTTP

http://www.mysite.com/index.html Static Resource

REST

Brother of HTTP

http://www.mysite.com/Customer/1001 Dynamic Resource returning XML or JSON content

REST

Brother of HTTP

http://www.mysite.com/Customer/1001/Picture Dynamic Resource returning an image

REST

Brother of HTTP

http://www.mysite.com/pictures/logo.png Image Resource

http://www.mysite.com/index.html Static Resource

http://www.mysite.com/Customer/1001 Dynamic Resource returning XML or JSON content

http://www.mysite.com/Customer/1001/Picture Dynamic Resource returning an image

REST

Brother of HTTP

But

REST <> HTTP

REST over any message protocol

even stand-alone REST

REST Interfaces

HTTP Verbs

GET

POST

PUT

DELETE

CRUD Operations

READ

CREATE

UPDATE

DELETE

REST Interfaces

HTTP Verbs

GET

POST

PUT

DELETE

SQL Statements

SELECT

INSERT

UPDATE

DELETE

REST Interfaces

Verbs + URI vs

GET customer/123

POST customer

PUT order/456

DELETE order/456

Methods

GetCustomer

NewCustomer

ModifyOrder

DeleteOrder

REST Content

Transmitted

by representation

XML

<Customer> <ID>1234</ID> <Name>Dupond</Name> <Address>Tree street

</Address> </Customer>

JSON

{"Customer": {"ID":1234,

"Name":"Dupond", "Address":"Tree street"

} }

REST Content Troll

XML vs

Type safe

SOAP standard

Binary (CDATA)

Validation (XSDL)

JSON

Truly human-readable

Native AJAX / JavaScript

Compact (UTF-8 friendly)

Simple to implement

RAD → MVC / MVVM

RAD

MVC & MVVM

SOA

RAD

Our beloved Delphi

RAD

Mixes UI and logic

→ Maintenance

Evolution

Test

Multi-platform

Nightmare

MVC

Isolate domain logic from UI

Model

View

Controller – View Model

Model

View

Controller

MVC process

MVVM

MVC & SOA

View

Controller

Model

MVC & Web

View

Controllers

Model

SQL/NoSQL→ ORM/ODM

SQL

NoSQL

ORM

ODM

SQL

De facto Standard

ACID by transactions

Relational (RDBMS)

NoSQL

Not Only SQL

NoSQL

Not Only SQL

Graphs

Aggregates

NoSQL

Graph-oriented

NoSQL

Aggregate-oriented

NoSQL

Aggregate = all data in a given context

(boundaries for ACID)

SQL / NoSQL

Data Modeling

SQL / NoSQL

SQL

Normalization

Consistency

Transactions

Vertical scaling

NoSQL

Denormalization

Duplicated data

Document ACID

Horizontal scaling

SQL

De facto Standard?

ACID by transactions

Relational? (RDBMS)

ORM

Object Relational Mapping

CRUD on objects

vs

SQL on relational tables

ORM

Object Relational Mapping

ORM

Object Relational Mapping

By convention

By configuration

Database-First / Code-First

ORM

In practice

myObject.Value := 10;

myContext.Update(myObject);

UPDATE OBJTABLE SET …

01010101001110011111

ORM

Benefits

Stay at OOP level

Manage SQL flavors

Persistence Ignorance

Optimize SQL

Cache

ORM

No magic bullet

Hard task

Hidden process

Legacy (tuned) SQL

Performance

NoSQL

Aggregate = all data in a given context

These documents map our objects!

ODM

Object Document Mapping

Aggregate = Object

Flexible Schema

Denormalized

OOP → SOLID

Interfaces

SOLID

Just because you can doesn’t mean you should

Interfaces

What, not how

A type that comprises

abstract virtual methods

Rely on abstraction

rather than implementation

Interfaces

Abstraction is your health

Publish classes as services

Test, mock

Write SOLID code

Interfaces

Abstraction is your health

Publish classes as services

Test, mock

Write SOLID code

and manage memory for you

Interfaces

Abstraction is your health

Publish classes as services

Test, mock

Write SOLID code

and manage memory for you

unless zeroing weak pointers

SOLID Principles

Single responsibility

Open/closed

Liskov substitution

Interface segregation

Dependency inversion

.. unleash interfaces!

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

Cross Cutting Features

UTF-8 JSON

TDynArray

TDocVariant

Logging

Testing

Compression

Crypto

PDF

Mustache

SpiderMonkey

Uncoupled features: could be used

without the ORM/SOA/MVC framework

SynCommons

UTF-8 JSON

From the ground up

With objects, records,

dynamic arrays, variants, any value

Performance and integration

SynCommons

TDynArray

Wrapper to an existing dynamic array

TList<> on steroids

e.g. sorting, search,

binary or JSON serialization using enhanced RTTI if available

SynCommons

TDynArray

In conjunction with records and variants:

value objects

data transfer objects (DTO)

SynCommons

TDocVariant

Stores documents

objects, arrays, variants

with low overhead

natively JSON

with late-binding support

SynCommons

TDocVariant var V: variant; // stored as any variant

...

TDocVariant.New(V); // or slightly slower V := TDocVariant.New;

V.name := 'John'; // property accessed via late-binding

V.year := 1972;

// now V contains {"name":"john","year":1972}

SynCommons

TDocVariant V.name := 'Mark'; // overwrite a property value

writeln(V.name); // will write 'Mark'

V.age := 12; // add a property to the object

writeln(V.age); // will write '12'

writeln(V); // implicit conversion to JSON string

// i.e. '{"name":"Mark","age":12}'

writeln(VariantSaveJSON(V1)); // as RawUTF8

SynCommons

TDocVariant + mORMot.pas TSQLRecordData = class(TSQLRecord) private fName: RawUTF8; fData: variant; public published property Name: RawUTF8 read fTest write fTest

stored AS_UNIQUE; property Data: variant read fData write fData; end;

TDocVariant + mORMot.pas

property Data: variant read fData write fData;

We store a TDocVariant in Data

to mutate a SQL database

into a NoSQL engine

TDocVariant + mORMot.pas

property Data: variant read fData write fData;

We store a TDocVariant in Data

to mutate a SQL database

into a NoSQL engine

TDocVariant + mORMot.pas

var aRec: TSQLRecordData;

aID: integer;

begin

// initialization of one record

aRec := TSQLRecordData.Create;

aRec.Name := 'Joe’;

// create a TDocVariant

aRec.data := _JSONFast('{name:"Joe",age:30}');

// or we can use this overloaded constructor

aRec := TSQLRecordData.Create(

['Joe',_ObjFast(['name','Joe','age',30])]);

TDocVariant + mORMot.pas

// now we can play with the data, e.g. via late-binding:

writeln(aRec.Name); // will write 'Joe'

writeln(aRec.Data); // write '{"name":"Joe","age":30}

// one year older

aRec.Data.age := aRec.Data.age+1;

// add a property to the schema

aRec.Data.interests := 'football';

aID := aClient.Add(aRec);

// we stored {"name":"Joe","age":31,"interests":"footbal"}

aRec.Free;

// now we can retrieve the data e.g. via aID

end;

TDocVariant + mORMot.pas

property Data: variant read fData write fData;

Data will be stored as TEXT

in the underlying RDBMS

TDocVariant + mORMot.pas

property Data: variant read fData write fData;

Data will be stored as TEXT

in the underlying RDBMS

Of course, if the database is a MongoDB engine,

the data will be stored as a true BSON document

SynCommons

Logging

Low overhead

Local or remote

Fast viewer tool

Exception catch, stack trace

Used by the whole framework

SynCommons

Testing

Light and cross-platform

Convention over configuration

Stubs and mocks

Compression

SynZip

faster unzip

SynLZO

SynLZ

speed symmetric

SynCrtSock

Cross-platform Network library

Socket WinHTTP WinINet clients

Optimized HTTP server

IOCP driven

http.sys kernel-mode

SynCrypto

SHA 1

SHA 256

AES 128

AES 192

AES 256

MD5

Pascal or optimized asm

SynPDF

From TCanvas to PDF

Unicode

Font embedding

Encryption

SynPDF

From TCanvas to PDF

Unicode

Font embedding

Encryption

Code-based report engine

SynMustache

Mustache template system

Data context as TDocVariant

UTF-8 JSON

With extensions

SynMustache

Data Context { "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": true }

SynMustache

Template <h1>{{header}}</h1> {{#items}} {{#first}} <li><strong>{{name}}</strong></li> {{/first}} {{#link}} <li><a href="{{url}}">{{name}}</a></li> {{/link}} {{/items}} {{#empty}} <p>The list is empty.</p> {{/empty}}

SynMustache

Result <h1>Colors</h1>

<li><strong>red</strong></li>

<li><a href="#Green">green</a></li>

<li><a href="#Blue">blue</a></li>

<p>The list is empty.</p>

SynMustache

Data Context { "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": true }

SynMustache

Template <h1>{{header}}</h1> {{#items}} {{#first}} <li><strong>{{name}}</strong></li> {{/first}} {{#link}} <li><a href="{{url}}">{{name}}</a></li> {{/link}} {{/items}} {{#empty}} <p>The list is empty.</p> {{/empty}}

SynMustache

Result <h1>Colors</h1>

<li><strong>red</strong></li>

<li><a href="#Green">green</a></li>

<li><a href="#Blue">blue</a></li>

<p>The list is empty.</p>

SynMustache

Data Context { "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": true }

SynMustache

Template <h1>{{header}}</h1> {{#items}} {{#first}} <li><strong>{{name}}</strong></li> {{/first}} {{#link}} <li><a href="{{url}}">{{name}}</a></li> {{/link}} {{/items}} {{#empty}} <p>The list is empty.</p> {{/empty}}

SynMustache

Result <h1>Colors</h1>

<li><strong>red</strong></li>

<li><a href="#Green">green</a></li>

<li><a href="#Blue">blue</a></li>

<p>The list is empty.</p>

SynMustache

Data Context { "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": true }

SynMustache

Template <h1>{{header}}</h1> {{#items}} {{#first}} <li><strong>{{name}}</strong></li> {{/first}} {{#link}} <li><a href="{{url}}">{{name}}</a></li> {{/link}} {{/items}} {{#empty}} <p>The list is empty.</p> {{/empty}}

SynMustache

Result <h1>Colors</h1>

<li><strong>red</strong></li>

<li><a href="#Green">green</a></li>

<li><a href="#Blue">blue</a></li>

<p>The list is empty.</p>

SynSM

Latest Spidermonkey

Javascript JIT engine

Call JS from Delphi

TSMVariant for late binding

SynSM

Latest Spidermonkey

Javascript JIT engine

Call JS from Delphi

TSMVariant for late binding

SynSM + mORMot = multi-threaded node.js

Sample 23

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

DB Layer

SynMongoDB

NoSQL

SynDB

SQL

Uncoupled features: could be used

without the ORM/SOA/MVC framework

SynMongoDB

MongoDB native access

BSON types - TBSONVariant

TDocVariant

Extended JSON

Sample 24

SynDB

Direct RDBMS access layer

Not linked to DB.pas

Multi providers

UTF-8 JSON

Interface based

Knows SQL dialects

SynDBExplorer

SynDB

Not linked to DB.pas

Enter the 21th century

Less data types

By-pass slow TDataSet

Unicode even before Delphi 2009

Array binding

Native JSON support

SynDB

Providers

SynDB

Connect to a DB

var Props: TSQLDBConnectionProperties; ... Props := TOleDBMSSQLConnectionProperties.Create( '.\\SQLEXPRESS','AdventureWorks2008R2','',''); try UseProps(Props); finally Props.Free; end;

SynDB

Execute statements

procedure UseProps(Props: TSQLDBConnectionProperties); var I: ISQLDBRows; begin I := Props.Execute( 'select * from Sales.Customer '+ 'where AccountNumber like ?',['AW000001%']); while I.Step do assert(Copy(I['AccountNumber'],1,8)='AW000001'); end;

SynDB

Late-binding

procedure UseProps(Props: TSQLDBConnectionProperties); var Row: Variant; begin with Props.Execute( 'select * from Sales.Customer '+ 'where AccountNumber like ?‘,['AW000001%'],@Row) do while Step do assert(Copy(Row.AccountNumber,1,8)='AW000001'); end;

SynDB

TQuery emulation

Q := TQuery.Create(aSQLDBConnection); try Q.SQL.Clear; // optional Q.SQL.Add('select * from DOMAIN.TABLE'); Q.SQL.Add(' WHERE ID_DETAIL=:detail;'); Q.ParamByName('DETAIL').AsString := '1234'; Q.Open; Q.First; // optional while not Q.Eof do begin assert(Q.FieldByName('id_detail').AsString='1234'); Q.Next; end; Q.Close; // optional finally Q.Free; end;

SynDB

Fast read/only TDataSet ds1.DataSet := ToDataSet(ds1, aProps.Execute('select * from people',[]));

Read/write TClientDataSet ds1.DataSet := ToClientDataSet(ds1, aProps.Execute('select * from people',[]));

SynDB

Remote access via HTTP

SynDB

Remote access via HTTP

http.sys based server

SynLZ compression

Digital signature

Authentication

SynDB

Remote access via HTTP

Mutate SQLite3 into a

high performance Client-Server RDBMS

No library to deploy on Client side

Easy remote hosting on Server side

SynDB

Remote access via HTTP

Mutate SQLite3 into a

high performance Client-Server RDBMS

No library to deploy on Client side

Easy remote hosting on Server side

SynDBExplorer

Manage and request your DBs

Any supported database

High performance grid

Export to CSV or SQLite3

SQLite3 integrated

Remote server or client

SynDBExplorer

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

ORM/ODM/SOA/MVC

ORM/ODM/SOA/MVC

RESTful

ORM

SOA

MVC

RESTful ORM

Not an ORM

with a transmission layer

But a RESTful ORM

from the ground up

TSQLRest

RESTful access

Convention over configuration

CRUD methods - Cache

Authentication – Authorization

Services

On Client or Server side

TSQLRest

TSQLRest

TSQLRest

TSQLRest

TSQLRestServer

Server Storage

In-memory

SQLite3 local

External SQL

External NoSQL

Redirected

TSQLRestServer

TSQLRestServer

Per table redirection

TSQLRestClient

Client Access

In process

Library

HTTP

Named pipes

Windows messages

TSQLRest Cache

TSQLRecord

Convention over configuration

TSQLSampleRecord = class(TSQLRecord) private fQuestion: RawUTF8; fName: RawUTF8; fTime: TModTime; published property Time: TModTime read fTime write fTime; property Name: RawUTF8 read fName write fName; property Question: RawUTF8 read fQuestion write fQuestion; end;

TSQLRecord

Convention over configuration

TSQLSampleRecord = class(TSQLRecord) private fQuestion: string; fName: string; fTime: TModTime; published property Time: TModTime read fTime write fTime; property Name: string read fName write fName; property Question: string read fQuestion write fQuestion; end;

TSQLModel

Define your data model

function CreateSampleModel: TSQLModel; begin result := TSQLModel.Create([TSQLSampleRecord]); end;

Shared on both Client and Server side

Database: TSQLRest

CRUD Operations

procedure TForm1.FindButtonClick(Sender: TObject); var Rec: TSQLSampleRecord; begin Rec := TSQLSampleRecord.Create( Database,'Name=?',[StringToUTF8(NameEdit.Text)]); try if Rec.ID=0 then QuestionMemo.Text := 'Not found' else QuestionMemo.Text := UTF8ToString(Rec.Question); finally Rec.Free; end; end;

Database: TSQLRest

CRUD Operations

procedure TForm1.AddButtonClick(Sender: TObject); var Rec: TSQLSampleRecord; begin Rec := TSQLSampleRecord.Create; try Rec.Name := StringToUTF8(NameEdit.Text); Rec.Question := StringToUTF8(QuestionMemo.Text); if Database.Add(Rec,true)=0 then ShowMessage('Error adding the data') else begin NameEdit.Text := ''; QuestionMemo.Text := ''; NameEdit.SetFocus; end; finally Rec.Free; end; end;

TSQLRestServer

var Model: TSQLModel; Database: TSQLRestServerDB; HTTPServer: TSQLHttpServer; … Model := CreateSampleModel; Database := TSQLRestServerDB.Create(Model,'data.db3'); Database.CreateMissingTables; HTTPServer := TSQLHttpServer.Create('8080',[Database]); HTTPServer.AccessControlAllowOrigin := '*';

TSQLRestClient

var Model: TSQLModel; Database: TSQLRest; … Model := CreateSampleModel; Database := TSQLHttpClient.Create(ServerIP,'8080',Model);

Sample 04

Sample 04

http://localhost:8080/root

http://localhost:8080/root/samplerecord

disable authentication…

http://localhost:8080/root/samplerecord

http://localhost:8080/root/samplerecord/1

TSQLRestServer

External SQL var Model: TSQLModel; Props: TSQLDBConnectionProperties; Database: TSQLRestServerDB; HTTPServer: TSQLHttpServer; … Model := CreateSampleModel; Props := TODBCConnectionProperties.Create('', 'Driver=PostgreSQL Unicode';…','',''); VirtualTableExternalRegisterAll(Model,Props); Database := TSQLRestServerDB.Create(Model,':memory:'); Database.CreateMissingTables; HTTPServer := TSQLHttpServer.Create('8080',[Database]); HTTPServer.AccessControlAllowOrigin := '*';

Sample 28

TSQLRecord

Mapping by Convention

TSQLRecordPeopleExt = class(TSQLRecord) .. published property FirstName: RawUTF8 index 40 property LastName: RawUTF8 index 40 property Data: TSQLRawBlob property YearOfBirth: integer property YearOfDeath: word property LastChange: TModTime property CreatedAt: TCreateTime end;

TSQLRecord

Mapping by configuration

Model := TSQLModel.Create([TSQLRecordPeopleExt],'root'); VirtualTableExternalRegister( Model,TSQLRecordPeopleExt,Props,'Test.People');

TSQLRecord

Mapping by configuration

Model := TSQLModel.Create([TSQLRecordPeopleExt],'root'); VirtualTableExternalRegister( Model,TSQLRecordPeopleExt,Props,'Test.People'); Model.Props[TSQLRecordPeopleExt].ExternalDB. MapField('ID','Key'). MapField('YearOfDeath','YOD');

TSQLRecord Change Tracking

Objects Time Machine

Database.TrackChanges([TSQLInvoice]);

TSQLRecord Change Tracking

Objects Time Machine

Database.TrackChanges([TSQLInvoice]); aInvoice := TSQLInvoice.Create; aHist := TSQLRecordHistory.CreateHistory( aClient,TSQLInvoice,400); try writeln('History Count: ',aHist.HistoryCount); for i := 0 to aHist.HistoryCount-1 do begin aHist.HistoryGet(i,aEvent,aTimeStamp,aInvoice); writeln; writeln('Event: ',ord(aEvent))^); writeln('TimeStamp: ',TTimeLogBits(aTimeStamp).ToText); writeln('Identifier: ',aInvoice.Number); end;

BATCH

Send all modifications at once

“Unit of Work” pattern

Array Binding or Multiple INSERT

Huge performance boost

Sample 15

SOA

Interface-based services

Design by contract

Factories

Instances live mode

REST UTF-8 JSON Security

Thread safety

SOA

Define the contract

type ICalculator = interface(IInvokable) ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}'] /// add two signed 32 bit integers function Add(n1,n2: integer): integer; end;

SOA

Implement the contract

type TServiceCalculator = class(TInterfacedObject, ICalculator) public function Add(n1,n2: integer): integer; end; function TServiceCalculator.Add(n1, n2: integer): integer; begin result := n1+n2; end;

SOA

Publish the contract on the Server Side

RestServer.ServiceRegister( TServiceCalculator,[TypeInfo(ICalculator)],sicShared);

Define the contract on the Client Side

RestServer.ServiceRegister( [TypeInfo(ICalculator)],sicShared);

SOA

Use the service var I: ICalculator; begin I := Rest.Services<ICalculator>; if I<>nil then result := I.Add(10,20); end; var I: ICalculator; // for older versions of Delphi begin if Rest.Services['Calculator'].Get(I) then result := I.Add(10,20); end;

On both client and server sides

Sample 14

MVC/MVVM

Auto Generated UI

Dynamic Web Sites

SynFile

Web Apps

Classic MVC

Web Apps

Model

View

Controller

ORM

Mustache

IMVCApplication

Classic MVC

Web Apps

Model

View

Controller

MVCModel.pas

*.html

MVCViewModel.pas

Blog MVC Sample

Web Apps

Implement a Controller

method name → page name

var const params → URI params

var out params → Mustache context

Web Apps

Implement a Controller

procedure TBlogApplication.AuthorView(var ID: integer; out Author: TSQLAuthor; out Articles: variant); begin RestModel.Retrieve(ID,Author); Author.HashedPassword := ''; // no need to publish it if Author.ID<>0 then Articles := RestModel.RetrieveDocVariantArray( TSQLArticle,'','Author=? order by RowId desc limit

50',[ID],ARTICLE_FIELDS) else raise EMVCApplication.CreateGotoError(HTML_NOTFOUND); End;

→ /blog/AuthorView?....

Web Apps

Implement a Controller

procedure TBlogApplication.AuthorView(var ID: integer; out Author: TSQLAuthor; out Articles: variant);

http://localhost:8092/blog/mvc-info

→ /blog/AuthorView?ID=..[integer]..

{{Main}}: variant {{ID}}: integer {{Author}}: TSQLAuthor {{Articles}}: variant

Web Apps

/blog/AuthorView?ID=123

procedure TBlogApplication.AuthorView(var ID: integer; out Author: TSQLAuthor; out Articles: variant); begin

→ ID = 123 RestModel.Retrieve(ID,Author); Author.HashedPassword := ''; // no need to publish it if Author.ID<>0 then Articles := RestModel.RetrieveDocVariantArray( TSQLArticle,'','Author=? order by RowId desc limit

50',[ID],ARTICLE_FIELDS) else raise EMVCApplication.CreateGotoError(HTML_NOTFOUND); end;

Web Apps

Mustache Data Context

procedure TBlogApplication.AuthorView(var ID: integer; out Author: TSQLAuthor; out Articles: variant); begin RestModel.Retrieve(ID,Author); Author.HashedPassword := ''; // no need to publish it if Author.ID<>0 then Articles := RestModel.RetrieveDocVariantArray( TSQLArticle,'','Author=? order by RowId desc limit

50',[ID],ARTICLE_FIELDS) else raise EMVCApplication.CreateGotoError(HTML_NOTFOUND); end;

{{ID}} {{Author}} {{Articles}}

Sample 30

Web Apps

Sample 30

http://localhost:8092/blog/default

http://localhost:8092/blog/mvc-info

http://localhost:8092/blog/articleView?id=99

http://localhost:8092/blog/articleView/json?id=99

http://localhost:8092/blog/authorView?id=1

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

Server

Delphi

Win32 Win64

XE7 XE6 XE5 XE4 XE3 XE2

XE1 XE0 XE-1 XE-2 XE-3 XE-4 XE-5

FPC

Win32 Linux-x86 Linux-ARM

2.7.1 svn (2.6.4)

Server

Delphi

Win32 Win64

XE7 XE6 XE5 XE4 XE3 XE2

XE 2010 2009 2007 2005 7 6

FPC

Win32 Linux-x86 Linux-ARM

2.7.1 svn (2.6.4)

Clients

Delphi

Win32 Win64 OSX Android iOS

XE7 XE6 XE5 XE4 XE3 XE2

XE 2010 2009 2007 2005 7 6 5

FPC

All platforms

2.6.x 2.7.x

Clients

Smart Mobile Studio 2.1

HTML5

Mobile / PhoneGap

any REST JSON Client

AJAX C# Java …

Sample 27

Sample 27

Project14ServerHttpWrapper

http://localhost:888/root/wrapper/

+ SMS Project14Client

RegressionTests + LogView server

RegressionTestsServer + SMS Sample 29

RoadMap

Data Replication

Master / Slave

P2P

Offline mode

Event-Driven

http://synopse.info/fossil/wiki?name=RoadMap

mORMot & Friends

Open Source

Architecture & Design

Cross-Cutting features

DB Layer

ORM/ODM/SOA/MVC

Cross platform

Q&A

http://synopse.info/files/pdf/BeDelphi2014.pdf