We have just released a set of slides introducing ORM, SOA, REST, JSON, MVC, MVVM, SOLID, Mocks/Stubs, Domain-Driven Design concepts with Delphi, and showing some sample code using our Open Source mORMot framework. You can follow the public link on Google Drive! This is a great opportunity to […]
With revision 1.18 of the framework, we just introduced two new custom types
The second custom type (which handles MongoDB-specific extensions -
ObjectID or other specific types like dates or binary) will
be presented later, when dealing with MongoDB support in
mORMot, together with the BSON kind of content. BSON /
MongoDB support is implemented in the
We will now focus on
TDocVariant itself, which is a generic
container of JSON-like objects or arrays.
This custom variant type is implemented in
SynCommons.pas unit, so
is ready to be used everywhere in your code, even without any link to the
mORMot ORM kernel, or MongoDB.
TDocVariant implements a custom variant type which can be used
to store any JSON/BSON document-based content, i.e. either:
- Name/value pairs, for object-oriented documents;
- An array of values (including nested documents), for array-oriented documents;
- Any combination of the two, by nesting
Here are the main features of this custom variant type:
- DOM approach of any object or array documents;
- Allow nested documents, with no depth limitation but the available memory;
- Assignment can be either per-value (default, safest but slower when containing a lot of nested data), or per-reference (immediate reference-counted assignment);
- Very fast JSON serialization / un-serialization with support of MongoDB-like extended syntax;
- Access to properties in code, via late-binding (including almost no speed penalty due to our VCL hack as already detailed);
- Direct access to the internal variant names and values
arrays from code, by trans-typing into a
- Instance life-time is managed by the compiler (like any other
varianttype), without the need to use
- Optimized to use as little memory and CPU resource as possible (in contrast
to most other libraries, it does not allocate one
classinstance per node, but rely on pre-allocated arrays);
- Opened to extension of any content storage - for instance, it will perfectly integrate with BSON serialization and custom MongoDB types (ObjectID, RegEx...), to be used in conjunction with MongoDB servers;
- Perfectly integrated with our Dynamic
array wrapper and its JSON serialization as with the
- Designed to work with our mORMot ORM: any
TSQLRecordinstance containing such
variantcustom types as published properties will be recognized by the ORM core, and work as expected with any database back-end (storing the content as JSON in a TEXT column);
- Designed to work with our mORMot SOA: any
interface-based service is able to consume or publish such kind of content, as
variantkind of parameters;
- Fully integrated with the Delphi IDE: any
variantinstance will be displayed as JSON in the IDE debugger, making it very convenient to work with.
To create instances of such
variant, you can use some
_Obj() _ObjFast()global functions to create a
_Arr() _ArrFast()global functions to create a
_Json() _JsonFast() _JsonFmt() _JsonFastFmt()global functions to create any
variantobject or array document from JSON, supplied either with standard or MongoDB-extended syntax.
By default, during interface-based service call,
record parameter or function result will be serialized with
our proprietary binary (and optimized layout) - i.e.
RecordSave functions - then encoded in Base-64, to be
stored as plain text within the JSON stream.
One nice feature of the
TDynArray wrapper and its associated
methods, as defined and used in our framework, is the ability to serialize
any dynamic array as JSON content.
By default, only "standard" dynamic arrays (like
TIntegerDynArray) are serialized as true JSON array: other not
known kind of arrays are serialized as binary content, within a Base64
This is a very efficient solution for a pure Delphi application, since it will be fast and always works, but won't be easy to deal with from an AJAX client.
Applications can now supply a custom JSON serialization for any other
dynamic array, via the
Two callbacks are to be supplied for a dynamic array type information, in order to handle proper serialization and un-serialization of the JSON array.
2011-12-08. Pascal Programming
Among all trolling subject in forums, you'll find out the great Garbage Collection theme.
And, in Delphi, there is no such collector. We handle memory in several ways:
- Creating static variables - e.g. on the stack, inside a
- Creating objects with
classinstances allocated on heap - in at least three ways: with a
try..finally Freeblock, with a
TComponentownership model in the VCL, or by using an
interface(which creates an hidden
- Creating reference-counted variables, i.e.
variantkind of variables.
It is a bit complex, but it is also deadly powerful. You have several memory allocation models at hand, which can be very handy if you want to tune your performance and let program scale. Just like manual recycling at home will save the planet. Some programmers will tell you that it's a waste of cell brain, typing and time. Linux kernel gurus would not say so, I'm afraid.
Then came the big Apple company, which presented its new ARC model (introduced in Mac OS X 10.7 Lion) as a huge benefit for Objective-C in comparison with the Garbage Collection model. And let's face it: this ARC just sounds like the Delphi memory model.
There is a well known syndrome around, against ORM.
Do you remember The Vietnam of Computer Science article?
It is worth reading... and commenting.
Sounds a bit outdated by now. Tempus fugit!
That's it, our SynOleDB unit seems alive and running well.
OLE DB (Object Linking and Embedding, Database, sometimes written as OLEDB or OLE-DB) is an API designed by Microsoft for accessing data from a variety of sources in a uniform manner. It was designed as a higher-level replacement for, and successor to, ODBC, extending its feature set to support a wider variety of non-relational databases, such as object databases and spreadsheets that do not necessarily implement SQL.
SynOleDB unit implementation has been made with several points in
- Tested with SQL Server 2008 R2 and Oracle 11g providers from Microsoft and Oracle;
- Ability to be truly Unicode, even with pre-Unicode version of Delphi (like Delphi 7 or 2007);
- Could access any local or remote Database, from any version of Delphi, since it doesn't use the DB.pas unit or any related part of the VCL (even the Delphi 7 personal or the Turbo Explorer editions), just for free;
- Handle NULL or BLOB content for parameters and results;
- Avoid most memory copy or unnecessary allocation: we tried to access the data directly from the retrieved data buffer, just as given from OleDB;
- Was therefore designed to achieve the best performance possible: most time is spent in OleDB: the code layer added to the OleDB customer is very thin;
- True OOP architecture, to be used with any OleDB provider (allowing custom parameters or such), and even without OleDB (in the future, direct access to any DB client could be used);
- Could be safely used in a multi-threaded application/server (with one
- Allow parameter bindings of requests, with fast access to any parameter or
column name (thanks to
- Late binding of column values in Delphi code;
- Direct JSON content creation, with no temporary data copy nor allocation;
- Designed to be used with our
mORMot ORM, but could be used stand-alone (a full Delphi 7 client
executable is just about 200 KB), or even in any existing Delphi application,
thanks to a
2011-03-12. Pascal Programming
The SynCommons unit has been enhanced:
- new low-level RTTI functions for handling record types:
RecordSave, RecordSaveLength, RecordLoad;
TDynArray object, which is a wrapper around any dynamic
TDynArray, you can access any dynamic array (like
TIntegerDynArray = array of integer) using
properties and methods, e.g.
Count, Add, Insert, Delete, Clear, IndexOf,
Find, Sort and some new methods like
SaveTo which allow fast binary serialization
of any dynamic array, even containing strings or records - a
CreateOrderedIndex method is also available to create individual
index according to the dynamic array content. You can also serialize the array
content into JSON, if you wish.
What I like with dynamic arrays is that they are reference-counted, don't
Create/try..finally...Free code, and are well handled by
the Delphi compiler.
They are no replacement to a
TCollection nor a
TList (which are the standard and efficient way of storing
class instances), but they are very handy way of having a list of content or a
dictionary at hand, with no class nor properties definition.
You can look at them like Python's list, tuples (via records handling) and dictionaries (via
Find method), in pure Delphi. Our new methods
(about searching and serialization) allow most usage of those script-level
structures in your Delphi code.