I'm not doubting that it can be done, I'm just curious to see how it's done.
The resulting codebase was about 50kloc of C# and 10kloc of SQL, plus some cshtml and javascript of course. Sounds small, but it did a lot -- it contained a small CMS, a small CRM, a booking management system that paid commissions to travel agents and payments to tour operators in their local currencies, plus all sorts of other business logic that accumulates in 15+ years of operation. But because it was a monolith, it was simple and a pleasure to maintain.
That said, SQL is an objectively terrible language. It just so happens that it's typically the least of all the available evils.
I completely agree, it is absolutely essential to understand what SQL is emitted, and how SQL works. Perhaps the strawman argument against ORMs is that they preclude you from knowing SQL. They don't.
You will find that if you check sources they are lifted almost verbatim. LLMs are a way to cut through the noise, but they are rarely "authoring" anything here.
It's wild how far a little marketing can go to sell the same or an arguably worse product that used to be free and less unethical.
ORMs are way more trouble than they’re worth because it’s almost easier to write the actual SQL and just map the resulting table result.
Also, in many non-tech companies the database admins were historically a consistent IT resource even when no other developers were available, so SQL gets leveraged extensively. When your only tool is a hammer, most of your problems end up being weirdly nail shaped.
There are many others as well. Sure Rails/Laravel/Django people use the ORM supplied by their framework, but many of us feel it's un-necessary and limiting.
Limiting because for example many of them don't support cte queries(rails only added it a couple of years ago). Plus it get weird when sometimes you have to use sql.raw because your ORM can't express what you want.
Also transactions are way faster when done in a SQL function than in code. I have also seen people do silly things like call startTransaction in code and the do a network request resulting in table lock for the duration of that call.
Some people complain that writing postgres functions make testing harder, but with pglite it's a non issue.
As an aside I have seen people in finance/healthcare rely on authorization provided by their db, and just give access to only particular tables/functions to a sql role owned by a specific team.
So add another layer that has to be maintained/debugged when you don't have to?
People who write percentages make shit up 98% of the time.
Or in other words: Source?
Writing queries is trivial and in any marginally complex case I'll write something which beats the ORM for efficiency. I suppose they are a god send if you don't know SQL but you can learn SQL quite quickly.
ORMs are one of those things that a lot of people think is a replacement for knowing SQL. Or that ORMs are used as a crutch. That has nothing to do with it. Very similar to how people here talked about TypeScript 10 years ago in a very dismissive way. Not really understanding its purpose. Most people haven't used something like Entity Framework either which is game changing level ORM. Massive productivity boost, and LINQ rivals SQL itself in that you can write very small yet powerful queries equivalent to much more complex and powerful SQL.
Since then I've embraced ORMs for CRUD. I still double-check its output, and I'm not afraid to bypass it when needed.
I've definitely had issues when using sqlalchemy where some REST API type returns an ORM object that ends up performing many queries to pull in a bunch of unnecessary data. I think this is harder to do accidentally with SeaORM because the Rust type system makes hiding queries and connections harder.
Most of my usage of SeaORM has been as a type query builder, which is really what I want from an ORM. I don't want to have to deal with lining my "?" or "$1" binds or manually manipulate strings to build a query. IMO a good query builder moves the experience closer to writing actual SQL, without a query builder I find myself writing "scripts" to write SQL.
But that is the result of having multiple applications needing to enforce valid states in the database.
"Business logic" is a loose term. The database is the effective store for state so it must enforce states, eg by views, triggers, and procedures.
Other "business logic" can happen outside of the db in different languages. When individual apps need to enforce valid states, then complexity, code, etc grows exponentially.
At my new company, the use of stored procedures unchecked has really hurt part of the companies ability to build new features so I'm surprised to see what seems like sound advice, "don't use stored procedures", called out as a cargo cult.
If you don't have a good way to keep stored procedures in version control, test them and have them applied consistently across different environments (dev, staging, production) you quickly find yourself in a situation where only the high priests of the database know how anything works, and making changes is painful.
Once you have that stuff in git, with the ability to run automated tests and robust scripting to apply changes to all of your environments (I still think Django's migration system is the gold standard for this, though I've not seen that specifically used with stored procedures myself) their drawbacks are a lot less notable.
Git? (and migrations)
> change management
Again. Just like any other code.
> and automated tests.
Just write an automated test like you write any other kind of test?
My experience is following
1) Tx are faster when they are executed a sql function since you cut down on network roundtrip between statements. Also prevents users from doing fancy shenanigans with network after calling startTransaction.
2) It keeps your business logic separated from your other code that does caching/authorization/etc.
3) Some people say it's hard to test sql functions, but since pglite it's a non issue IMO.
4) Logging is a little worse, but `raise notice` is your friend.
> At my new company, the use of stored procedures unchecked has really hurt part of the companies ability to build new features
Isn't it just because most engineers aren't as well versed in SQL as they are in other programming languages.
Like any tool, you just have to understand when to use it and when not to.
If not, why would you then avoid putting code alongside your data at the database layer?
There are definitely valid reasons to not do it for some cases, but as a blanket statement it feels odd.
Stored procedures can do things like smooth over transitions by having a query not actually know or care about an underlying structure. They can cut down on duplication or round trips to the database. They can also be a nightmare like most cases where logic lives in the wrong place.
In contrast, every company I've joined that used Entity Framework had enterprise products that ended up being a tightly coupled mess from IQueryable<T> being passed around like the world's favourite shotgun.
You may not need to use an ORM, but hand writing SQL, especially CRUD, should be a terminable offense. You _cannot_ write it better than a process that generates it.
Just write SQL. I figured this out when I realized that my application was written in Rust, but really it was a Postgres application. I use PG-specific features extensively. My data, and database, are the core of everything that my application does, or will ever do. Why am I caring about some convenient abstractions to make it easier to work with in Rust, or Python, or whatever?
Nah. Just write the good SQL for your database.