ORM for Delphi

I wanted to share with you some experience about the ORM I used for my projects in Delphi. So many of you were questioned about the choice of the ORM framework to use. There are some old ones and new to choose from (the list is incomplete and you are welcome to complete it):

  • Marshmallow – open source ORM for Delphi for fans of Spring4D;
  • TMS Aurelius – a commercial ORM solution. Currently very powerful framework with a lot of features and a good community feedback;
  • DORM – very promising and looks solid Delphi ORM by Daniele Teti;
  • Bold – some legacy ORM solution which is not supported any more as far as I know;
  • tiOPF – Object persistence framework for Delphi. Files on sf.net are dated with 2008;
  • G-framework – but I can’t find any useful website or place where it is hosted;
  • mORMot framework – very specific ORM framework which is the most hard to understand. It was probably developed for own internal project but then later published. If you look at the code you find a bit weird formatting, but that’s matter of taste. The library is huge. The library is well documented and certain parts are unit tested. Most of the routines are performance bargains (they are really optimized well)! This library can be a really good choice for persistence, especially if you are planning to extend your application to n-tier architecture;
  • DevART EntityDAC – free/commercial ORM framework. Additionally to the ORM mapping the framework also supports the LINQ (yes, real LINQ-like) syntax for querying the data;
  • ExpressEntityMapping Framework from DevExpress (check https://www.devexpress.com/products/vcl/);
  • https://www.ormbr.com.br/ – open source brazilian ORM (just like Jiu Jitsu 🙂 ).

Currently I use the EntityDAC framework. There are two options to go with this product:

  1. Express edition – free version where most of the core things woks, but there is no visual designer for model generation from the database as well no dataset components for entities;
  2. Standard or Professional – commercial version which adds some very handful features and provides the good visual tool for modeling.

The use of the EntityDAC is quite simple from the beginning. The Entity Developer (for modeling) tool is amazing – all is as you expect:

  • Drag and drop tables from the database to the diagram;
  • Automatically resolves all foreign keys and creates the associations;
  • You can define the rules of field and table naming in generated classes;
  • You can adjust defaults, add constraints and associations manually.

The ORM part works almost the same way as Marshmallow or Aurelius. The nice thing which EntityDAC adds is their LINQ feature. That allows us to completely remove the “stringly-typed” stuff from our source code – so that our database fields and tables are validated at compile time! The cool thing is that you can build the where statement using standard flow operators to either include or exclude the filter:

var
  LExp: TExpression;
  LUser: IUserExpression;
  U: TUser;
begin
  ...
  LExp := LUser.UserName = 'admin';
  if BoxAutologin.Checked then
    LExp := LExp and LUser.Autologin;
  forin Context.GetEntities<TUser>(From(Context.User).Where(LExp)) do
    ...
end;

You can use all of the operators to build the conditions. If you ask how does that work then answer is simple – operator overloading done right! For more LINQ examples just go to their documentation.

But never try to completely replace the SQL with LINQ – on some cases it’s much more efficient to use the raw SQL instead of the LINQ to perform certain tasks – so choose the right tool for the right job!

Ok, so far so good. But what’s missing you ask?

For that I will just summarize the pluses and minuses from my point of view.

Pros

  • Free version available;
  • Very good database tool;
  • Good documentation;
  • Very good code quality (I had it with source) – they really use the design patterns and do good stuff in background!
  • Amazing LINQ language support in Delphi syntax;

Cons

  • Takes a bit to understand how to build more complex LINQ queries;
  • No IN statement support (however I do not know if any of ORMs has support for that);
  • Support team is kind of slow. Yes, it has bugs and I did report them, they confirmed them and replied “we will fix it asap…”. But the fixes are coming once in a half a year at best. Some of the issues are not fixed already for two releases since I reported them. I even am forced to fix their issues myself using the source code – that’s the only savior in this case until the support team starts working as good as DevExpress one 😀

12 comments

  1. Shouldn’t mocking a persistence service not mock the persistence service methods, not the value fields? I don’t get your point of generating interfaces for storing values…

    Like

    1. If your entities are simple DTOs (as I usually prefer it) then there is no need to mock them. Just mock the DAL that deals with them.

      Like

      1. I see your point. But what to do with legacy app which uses the ORM without DAL layer (it just does not exist) in certain classes? It’s always good an easy with well planned and correctly developed projects, but how to be with the legacy projects with tens years of codebase?

        Like

  2. I am using Aurelius for 3 years now, and others TMS components. There are considerable differences between architecture and programming styles for each major TMS package clearly showing different teams of programming. Regarding Aurelius and Flexcel I can tell you, take another closer look. The code is very nicely done, it is clear and basically bugs free (since is all DUnit based test). I have a big ERP running with it and going very well. The support for Aurelius is amazing, the documentation is short but direct to the point. I think your article is misleading when putting the DevArt as better ORM, it lacks many features available on Aurelius, Aurelius is bugs free, simple to use, full of features. Comparing current versions side to side will put Aurelius way up front.

    Like

  3. I have been using Bold for 12 years and it works fine. What about the other frameworks. Do they offer support for OCL queries ? Derived members in code or OCL ? Anyway those things allow me to do a lot with very little code.

    Like

  4. “No IN statement support (however I do not know if any of ORMs has support for that);”

    Actually Bold support it now. We implemented it ourselves as we have complete source.

    Like

  5. If you are stuck on an older Delphi version, like 7 or down, Synopse mORMot works – for the most part – well, and compiles without problem in such environment.
    There does not seem to be any detailed documentation, and it’s a huge pile to dig through. But it does work, and it’s free.

    Like

Leave a Reply