Object Relational Mapping is the idea of being able to write queries using the object-oriented paradigm in your preferred programming language. So this means we are trying to utilize our language to talk with the database instead of using SQL.
Why utilize ORM?
- It abstracts away the database system, so switching is easy.
- Your queries can be efficient than writing them with SQL.
- With ORM, you get lots of features out of the box for instance
- Transactions
- Migrations
- Seeds
- Streams
- Connection Pooling
Delphi community has several Delphi ORM libraries, and the DORM (Delphi ORM) by Daniele Teti is one of the popular and open-source libraries you can use.
DORM has many features available:
- Database agnostic (Do not require database changes!)
- Has one, has many, and belongs to relations support
- Mapping through file, attributes, or CoC
- Save and retrieve objects graph, not only single objects
- External (file) or internal (resource, json stream) configuration
- Interfaces based!
- FirebirdSQL (using UIB)
- Interbase (using UIB)
- SQLServer (using FireDAC driver)
- SQLite3 (using this SQLite3 wrapper
- and more!
procedure ObjVersionConcurrentTransactionsDEMO;
var
dormSession, dormSession1, dormSession2: TSession;
Customer, C1, C2: TCustomerV;
id: Integer;
begin
dormSession := TSession.CreateConfigured(
TStreamReader.Create(CONFIG_FILE), TdormEnvironment.deDevelopment);
try
Customer := TCustomerV.Create;
Customer.Name := 'Daniele Teti Inc.';
Customer.Address := 'Via Roma, 16';
Customer.EMail := 'daniele@danieleteti.it';
Customer.CreatedAt := date;
dormSession.Persist(Customer);
id := Customer.id;
WriteLn('Version: ', Customer.ObjVersion);
dormSession.Commit(true);
finally
dormSession.Free;
end;
// read the same object twice
dormSession1 := TSession.CreateConfigured(
TStreamReader.Create(CONFIG_FILE), TdormEnvironment.deDevelopment);
try
dormSession2 := TSession.CreateConfigured(
TStreamReader.Create(CONFIG_FILE), TdormEnvironment.deDevelopment);
try
// Two users gets the same record
WriteLn('User1 loads object ' + inttostr(id) + ' and close transaction');
C1 := dormSession1.Load<TCustomerV>(id);
dormSession1.Commit;
WriteLn('User2 loads object ' + inttostr(id) + ' and close transaction');
C2 := dormSession2.Load<TCustomerV>(id);
dormSession2.Commit;
// First user update the object and save it
C1.Name := 'John Doe';
C1.ObjStatus := osDirty;
WriteLn('User1 update object ' + inttostr(id));
dormSession1.Persist(C1);
dormSession1.Commit;
// The second user try to do the same
C2.Name := 'Jane Doe';
C2.ObjStatus := osDirty;
WriteLn('User2 try to update object ' + inttostr(id) + ' (an exception will be raised)');
dormSession2.Persist(C2); // raise EDORMLockingException
finally
dormSession2.Free;
end;
finally
dormSession.Free;
end;
end;