3 ms·
This is what you get when you let your ORM loose on the database without understanding JOINs. Especially, the bit where something like 'book.author.name' that l
by red_admiral 2mo ago
This is what you get when you let your ORM loose on the database without understanding JOINs. Especially, the bit where something like 'book.author.name' that looks like a simple field dereference actually is a method call on an ORM proxy object (book), via python's __getattr__ or similar, that fires off a new query if the data you want is not loaded yet.
Some ORMs let you specify the extent of the data that you want, like Hibernate has its own Hibernate Query Language.
At some point you are better off just writing SQL yourself, though. Even without join problems, if you ask an ORM to get the person with user id 123 and all you want is their name, the ORM cannot know that unless to tell it, and so you end up with a 'SELECT *' type query.
- cnity 2mo agoORMs are great. They make the easy queries remain easy and the harder queries impossible.
- tehlike 2mo agoThis is true but not super true in case of linq and related providers like efcore. Even nhibernate linq would do this.
- seki285 2mo agoYou should write a raw SQL query to grab just a user's name only when there's a need for that.
- ddorian43 2mo agoOr set lazy loadin to "raise" in the relationships and get exceptions if you dont explicitly join.
- red_admiral 2mo agoIs usually the right answer!
- BeetleB 2mo agoDealing with Django, they give quite a few ways to query data. For the small internal web site we ran, I've yet to encounter an N+1 situation that I didn't find an alternative Django API that I should have been using. Not saying you never need bare SQL on Django sites, but the Django ORM does have some sophisticated APIs to prevent this problem. > Even without join problems, if you ask an ORM to get the person with user id 123 and all you want is their name, the ORM cannot know that unless to tell it So ... tell it! You can specify in a query to fetch only certain data, and not the whole object.
- plaguuuuuu 2mo agoPeople always say this and my experience in C# has been the opposite. I've never wanted to reach for raw SQL and hardly ever do, only if its because there's no extension to do SKIP..LOCKED or something var name = dbContext.Users .Where(u => u.Id == 123) .Select(u => u.Name) .First();
- entropicdrifter 2mo agoI mean, you're definitely still writing a query in this case, just using a lazy-loading C# interface. An ORM in the traditional sense abstracts the details of the query itself fully away in favor of an object-oriented interface.
- fabian2k 2mo agoEF Core does not lazy load by default. You have to explicitly include relations if you want them on an entity. You can enable lazy loading, but in the default configuration you usually don't have the N+1 problem.
- entropicdrifter 2mo agoIsn't Linq a lazy-loading interface by default? The example they gave was a Linq query. I'm not a C# user in my professional life so I'm happy to be corrected, BTW, just citing the source of my misinterpretation
- fabian2k 2mo agoYes, but in this context this just means that until you call ToList()/ToListAsync() you have an IQueryable. That represents a query, but isn't executed yet. Only at the point where you call a method like ToList (in this case First() is the relevant one) is the actual DB query performed. The LINQ query in the comment above would only execute a single query like "SELECT name FROM users WHERE id = 123 LIMIT 1;" and would not even fetch the full entity, only the name.
- stephen 2mo ago> all you want is their name I have a WIP PR that addresses exactly this: https://github.com/joist-orm/joist-orm/pull/1967 https://github.com/joist-orm/joist-orm/pull/1967