It's not that your domain is different, it sounds more like you don't know how to use ORMs. ORMs don't have to manage migrations, they don't have to even write into the database. When dealing with a bad database design, it can be a legitimate tactic to use ORMs in read-only mode and have writes still as hand-rolled SQL. You can do database-first ORMs, as well as code-first, where the database design is king, not the POCO.
> The domain deals with a lot of things that are not in the database.
You can have non-serialized properties. You can even can over-ride serialization/de-serialization of individual properties
> The domain is one of many and deals with just a fraction of what is in the database
You can use different ORMs for different parts of your domain, you could even wrap multiple ORMs in a wrapper repo pattern if you want
> The domain deals with things stored in several databases
As above.
> The database was designed in the 90s and the domain is new
Tons of solutions for this, one easy one is using SQL Views, just ask Claude. The weird thing here is that I've now dealt with this IRL like 5 times and came to the opposite conclusion of you. I found wrapping a bad DB design with an ORM a great first step in fixing it, as the ORM effectively acts as an easy strangler pattern.
> It's not my database so I can't change it
You can still use ORMs, ORMs don't have to manage migrations. Though I feel sorry for you working somewhere you still have a DB guy gatekeeping the database design in 2026.
The point is, every one of your objections are pretty trivially solvable with many mature ORMs, because everyone else had the same problems two decades ago and instead of throwing up their hands and hand-rolling their SQL, the ORM tooling was improved.
You have mixed the posts you are replying to - the domain being different from the database is stipulated here.
I was giving examples of how this typically happens, and the reasons are entirely independent of whether or not an ORM is being used.
I am fully aware that you can handle any mess using an ORM as well, which is why I was surprised at the original claim that ORM's force proper domain models. I haven't observed that so I was genuinely curious.
Separately from that I have to say your suggestions of things to do to force an ORM into the situation are bad ideas. The complexity of custom serialization, various mapping hooks or attributes to bless individual properties will lead to pain and misery down the line.
Just accept the extra layer of DTO's. They're a detour over pure SQL but are at least easy to maintain and hold no surprises. They say there's a special place in hell for people who write SQL triggers and I think people who override ORM serializers are welcome there. ;-)
DTOs are one of the big code smells of a code base that does little but will be full of boilerplate. As soon as you see an automapper or a folder of DTOs you know you're in for some serious pain.
On the plus side you also know you can reduce the codebase by about 75%.
That doesn't sound at all like any ORM I've ever used. I've struggled in the past because The ones I've used are actively hostile to laying out data in the database in a way not proscribed by the ORMs philosophy. Heck of the ORMs I've used, one didn't support parameterized joins and the other didn't support joins at all.
---
It's not usually a DB guy gatekeeping, it's that multiple apps use the same database so layout changes are costly.
Except for the "multiple ORMs" part which is a level above it, it applies to the only one I've used extensively: Django for python. It has standard defaults, but just about everything overridable, and because models are python objects you can add methods or properties for extra data. There's even ways to define your own field types (the "serialization/de-serialization of individual properties"), which a decade ago people were using to provide json fields through libraries long before it was officially supported.
...and Django was like this 15 years ago when I first started using it. The core design hasn't changed, it just sounds like most other ORMs don't really know what they're doing.
>and Django was like this 15 years ago when I first started using it. The core design hasn't changed, it just sounds like most other ORMs don't really know what they're doing.
Django is an opinionated web framework that uses an ORM, not just an ORM.
Django can by all means be a great way to make a web site (I have little experience with it) but if you have a db that is accessed by various systems written in Java, dotnet, erlang or whatever else I suspect the smooth sailing of Django can run into headwinds quickly and the python plumbing you have to deal with then quickly becomes an issue in itself.
> but if you have a db that is accessed by various systems written in Java, dotnet, erlang or whatever else I suspect the smooth sailing of Django can run into headwinds quickly
Only if those systems are constantly adding/removing tables and columns. And adding isn't a problem, Django just ignores what's not specified in the models.
Django does have default table and column names based on the models that it prefers, but all of it is overridable in officially-supported ways. We're using it with mysql databases originally made for VB6 and C++ with inconsistent naming schemes that aren't even close to Django's defaults, that nowadays are also accessed by perl, php, and python. Most of our python uses are daemons that only use the models and none of the rest of the web framework - the models are defined in a common library they all use.
Usually it's due to one of these:
- The domain deals with a lot of things that are not in the database.
- The domain is one of many and deals with just a fraction of what is in the database.
- The domain deals with things stored in several databases.
- The database was designed in the 90s and the domain is new.
- It's not my database so I can't change it.
(Even for greenfield systems I don't think it's generally desirable that the database matches the domain model.)