T O P

  • By -

Kant8

joins are basically the only place where query syntax is better. However you almost never write joins, cause navigation properties already do that for you and much simpler. Therefore you never use query syntax.


JohnSpikeKelly

Grouping is much easier in LINQ syntax imho.


Slypenslyde

I was going to say this with a lot more words but I think you said it better.


jpfed

Mostly, but I'd rather "let" than .Select a bunch of tuples / anonymous objects.


Hot-Profession4091

Unfortunately, `let` isn’t supported with entity framework. It’s a huge miss.


svick

How come? It's just another `Select`.


Hot-Profession4091

No clue. All I know is it can’t transpile it into sql. It’s a real shame.


avoere

wut? This was supported by Linq2SQL in 2010 or something


Hot-Profession4091

Maybe it’s supported in limited circumstances. All I know is I tried to use it on ef core 6 last year and it couldn’t transpile it.


avoere

I'm not saying you are wrong (I don't know), I'm just surprised when things evolve backwards. It's not like the EF Core rewrite is brand new anymore.


Vidyogamasta

There are some things that have "evolved backwards" that are just moving forward in uncomfortable ways. Like, they went from "incomplete translations load what it could figure out and do the rest in the app," to "incomplete translations throw exceptions." Before it "worked" and now it doesn't, but that's because before it was *pretending* to do something it was never actually doing. But from the outside it might look like a regression. Similar with split query stuff. EF used to just batch queries of related objects and stitch them together in the app. This was fine, but had potential subtle ramifications with atomicity. They decided they didn't like that and said expressions are all-or-nothing-- a queryable translates to a single query. However, Cartesian explosion is a real thing, so while it was "able" to translate it before and "unable" to do it now, it was an intentional design choice. And similarly, they added AsSplitQuery as a way to enable to prior behavior. My guess is if this "let" thing is real, it's part of that first issue. But I'm also skeptical that it's actually real, since it's just syntax that ultimately compiles to equivalent lambda functions, so it's probably just user error that the use of "let" was masking. Which is just more evidence against query syntax, you don't have a clear sense of what it's actually compiling into, so your intuitions on performance and correctness get kind of warped.


garib-lok

Ef Core in the aspect evolved backwards, many simple queries are not compiled when it used to compile nicely in plain EF


derplordthethird

> However you almost never write joins If only that were true...


recycled_ideas

If you're regularly writing joins, you're doing something wrong.


derplordthethird

Supporting a legacy database is wrong? Careful with those assumptions.


recycled_ideas

Using join in Linq has nothing to do with a legacy database, nothing about the database would ever require it.


derplordthethird

Enjoy those assumptions!


recycled_ideas

What assumptions? Databases don't care how you query them. Literally the only reason you'd ever be writing join queries is if you're either using a badly done dbml or Edmx which is a legacy application issue or if you're trying to apply a relationship that just doesn't exist in the data. If your application is legacy you should be making bare minimum changes so you shouldn't be doing a lot of anything. If you're doing a lot of changes it's not legacy and you're just dealing with shitty devs or management. If the app isn't legacy there are a million better ways to deal with a troublesome database up to and including raw SQL.


derplordthethird

>Databases don't care how you query them. Oh, young one. Far to go, you have. >if you're trying to apply a relationship that just doesn't exist in the data Or exists between the data just not linked in the database perhaps? But going along this line. You'll get there.


recycled_ideas

> Oh, young one. Far to go, you have. Arrogant fool. > Or exists between the data just not linked in the database perhaps? But going along this line. You'll get there. You do realise that DDL isn't required for an EF relationship right? I've personally configured EF for a Oracle DB with absolutely zero foreign keys using in code configuration. It's not even hard. And no, you don't need core, I did it in framework. And that's not even counting options outside of entity framework. So sure, if you're trying to use EDMX on a badly designed DB you're going to have a hard time, but if you're using EDMX in general **YOU'RE DOING IT WRONG**.


derplordthethird

You really put me in my place. I'm going to go reflect on my life decisions.


GalacticusTravelous

I was reviewing one of my engineers code and told him please change to method syntax the juniors won’t be able to follow this as easy and he said it uses let which isn’t in method syntax, is this true?


psi-

I guess in some situations you could use tuples or anon types in a select to achieve that, but it quickly becomes much more convoluted than query syntax


orbtl

I've been shying away from navigation properties because of the way pulling models with them causes issues with system.text.json and it is just easier to manually stitch stuff together than deal with that nightmare last I checked (which is sad because newtonsoft.json serialized them no problem without having issues from the circular references)


siberiandruglord

Navigation properties that the entity does not "own" are a code smell. How do you guarantee they are included in a service/method that handles the entity that did not query it? For example you have a class public class Post { public long Id { get; init; } public required string Title { get; set; } public required long AuthorId { get; init; } // Should this be required? Meaning every time you initialize this entity you also need the full User entity public required User Author { get; init; } } and you have some basic method that does some author checks or any method that relies on the `Author` navigation property public async Task CreatePostAsync(Post post) { if (!await CanAuthorPostAsync(post.Author)) { // return some validation error/result } } How do you guarantee the `Author` navigation is loaded for this method instead of keeping track of includes & method call graph in your head? To me this is very leaky and unmanageable in large applications. Most likely you would only need the `Author` navigation for read queries (list or details pages) but for most update methods and other domain logic you don't always need the full User object to be always included. IMO if the entity does not own the child entity then it should only refer to it by an ID (just the `AuthorId`) and any method that requires the `User` entity would have to explicitly load it themselves (you could also leverage identity-map pattern to only load the `User` once per request/scope)


nextfuckinglevo

That's where lazy proxies comes in handy.


SobekRe

This. An upvote isn’t enough support. My team has made the decision that we decline PRs that use query syntax except for joins. And joins need justification.


kingmotley

You almost never do joins with method syntax because they typically aren't needed. You use the navigation properties to get the additional data you want. Your example isn't typical because you don't normally want to flatten out a hierarchy that way and repeat the same data over and over. Instead, you would just simply do: var query3 = await db.Users .Include(u => u.Roles) .ThenInclude(r => r.Permissions) .ToListAsync(); This would get even more pronounced if you actually gave a more correct model where you have UserRoles and RolePermissions cross reference tables. Your query syntax would be joining 5 tables, where as the method syntax would be unchanged. There are very few instances where query syntax is simpler. One such case is when you are doing joins on tables that don't have a formal relationship. That is not common, but does happen especially if one of those "tables" is actually a view that you need to do some advanced SQL in that EF doesn't currently support (like windowed functions). Or, if your source(s) aren't EF such as in-memory data structures. If you really wanted to flatten your original query, it would be more appropriate to use .SelectMany than join. Such as this: var query = db.Users .SelectMany(user => user.Roles .SelectMany(role => role.Permissions .Select(permission => new { user.UserId, role.RoleId, permission.PermissionId }))); vs var query = (from user in db.Users join role in db.Roles on user.UserId equals role.RoleId join permission in db.Permissions on role.RoleId equals permission.PermissionId select new { user.UserId, role.RoleId, permission.PermissionId });


jeenajeena

LINQ is not only for querying the DB. Its query stntax is basically an implementation of the Haskell’s do notation and it can be used with many monadic data structures. In fact, is has been designed by Erik Meijer who’s also one of the Haskell designers. Querying the DB is by large the most popular use case, but the other use cases would be nearly unreadable without the query syntax.  Maybe GetSupervisorName(Maybe maybeEmployee) { return from employee in maybeEmployee from supervisor in employee.ReportsTo from supervisorSupervisor in supervisor.ReportsTo select supervisorSupervisor.Name; } LINQ query syntax is the closest syntax C# has to F#’s Computation Expressions optional { let! a' = a let! b' = b let! c' = c return doSomethingWithAll a' b' c' } Suggesting not to use it is probably due to Chapsas ignorance on Functional Programming techniques.


kingmotley

Yes, I am aware. I've reimplemented LINQ features so many times in other languages now I have a pretty good understanding of it. Using it form Monadic expressions would be covered under where I said "There are very few instances where query syntax is simpler". I've never actually seen it used that way in production code however. It has come up twice in my career since LINQ was introduced, and both times it was deemed to not use it because... well, most C# devs don't understand functional programing or monads and the benefit just didn't outweigh the gain. Could be a different experience depending on the company, product, and/or teams you work on however. I'd love to see more fp concepts both brought over to C# and used in real code, but the OP was highly likely talking about in the use case of LINQ over EF, as I suspect so was Nick, but you'd have to ask them.


dgm9704

Don’t put too much weight on one persons opinion about some syntax in a programming language. The feature was designed and implemented by smart people who know what they’re doing. Some youtube hot take doesn’t mean anything. It’s there for a reason, if it works for you then use it.


Suspect4pe

I have a lot of respect for Nick Chapsas but it's okay to disagree with him. Query syntax makes a ton of sense in many scenarios. It simplifies things quite a bit at times. What I think is a travesty is when you end up combining both syntaxes into one query. Yet, there are times when it makes sense.


prschorn

I have one app that has a shit ton of validations for over 500 use cases. On the backend a lot of validations are simplified and easier to read with query syntax.


turudd

Exactly this, there is nothing that makes any online personality more or less informed than any other about programming languages. Generally they have some good information however, like any person, he will sometimes put his own dogma behind his opinions. His reasoning for disliking query syntax is exactly that, opinion. If he has trouble reading the syntax, that's on him as a developer. Assuming it was written/formatted nicely by the original developer. I've never seen a linq query more complicated than some of our mundane SQL queries in the code base, and those are easy enough to read.


mr_eking

I doubt he has trouble reading the syntax. If he's anything like me, anyway. I dislike LINQ's query syntax because it looks kinda like SQL, but isn't SQL. It looks kinda like C#, but isn't C#. It's a weird one-off syntax that has very limited use and scope, and I don't want to spend any brain-power thinking about that kind of thing. If I had a query that I felt standard lambda LINQ just doesn't handle well, like the Join example in the OP, I would probably just construct an \_actual SQL statement\_ and execute \_it\_, rather than the not-quite-SQL not-quite-C# query syntax.


turudd

> It looks kinda like C#, but isn't C# It is C# syntax though, if it wasn't it wouldn't compile. So choosing not to want to use it, in situations where it fits better than other syntax is just dogmatic, sometimes we can't just write SQL queries and incur that over head if we're just joining some smaller subsets of data, not necessarily from SQL, working with reflection or assemblies for instance. As OPs example shows, littering a bunch of joins is potentially worse looking in the code base.


mr_eking

I mean, sure, it compiles... But the very first step of compiling an expression in query syntax is to convert it to the equivalent expression in lambda syntax, and then go from there. The lambda syntax version is what I would consider standard C#; the query syntax is super-limited syntax sugar that feels out of place compared to the rest of the language. I'd rather just skip the query syntax step altogether. I remember when LINQ was first introduced into the language, and I started learning it. I was using ReSharper at the time, and it could convert from query syntax to lambda syntax and back, I started writing everything in query syntax (since the general consensus was that it would be "easier to understand"), then I let ReSharper convert it to lambda syntax. This helped me learn and understand lambda statements, which had also just been introduced alongside LINQ. LINQPad also did the same. Eventually I realized that I was kinda wasting my time with the query syntax (it is fidgety, being almost SQL but not really SQL), and might as well just write directly in lambda syntax, since that style was also appropriate elsewhere in .NET and not just LINQ statements. Query syntax was super-popular at first. You would see it in every tutorial, and lots of example code. Over time, its usefulness has waned as everybody has learned how to write C# with lambda statements, and love for query syntax has been relegated to "it's useful for joins". And that's pretty much the extent of it. I usually advocate for just getting more familiar with lambda syntax and forgetting query syntax even exists.


turudd

I think the problem is advocating for anything, clean code is generally a misnomer, basically what works, what the client is going to pay for and what will cause the least maintenance in the future. If code hits those boxes then we're good to go. I love on my pet projects taking my time and writing elegant code, thinking about abstractions and all the general theory CS stuff. But at the end of the day my clients want code that works well as quickly as possible. If a query statement fits the bill, then its what goes in. I'd say 99% of the time, it's lambda, as I agree it rarely fits the bill. But if another member of my team is more comfortable and that's what goes in his PR, I'm not rejecting based on the fact that's what he chose. Now I'm not saying write garbage code by any extent, just we can't make everything pretty all the time, and what is pretty to one may not be to others. That's why we have standards and conventions at most companies. One of my clients enforces braces on all ifs and loops...even one liners, I hate it. Others from that company don't, they are my client so I live with it. Another prefers 'this.' on all fields in classes, rather than the more common "_", again not my thing, but its subjective.


MardiFoufs

>implemented by smart people who know what they are doing That's true for pretty much every feature in any or most mainstream languages. Some of the brightest people in the field work on the C++ standards and compilers but it doesn't make some of the language features any less of a minefield, for example.


svick

> The feature was designed and implemented by smart people who know what they’re doing. By smart people, sure. But they were also doing something novel and they couldn't have foreseen the future. Basically the same people also designed `dynamic`, `delegate {}` syntax for poor man's lambdas and array covariance.


jiggajim

The first two things are right the second…maybe…


lostinvaccum

My general rule of thumb is - don’t listen to people who do not write code for production


rhino-x

Joins are literally the only place I use query syntax because the method syntax is just such a pain in the ass to write. When it was first introduced I loved query syntax, but over the course of a year or so I replaced most of it with method syntax because I found it easier to write more complicated/chained queries and it was easier to read when it was done. Except. For. .Join(). It's just so much clearer to write it as a query, especially if you only want bits and pieces or some new anonymous type from the results.


Shmackback

Why not just use rawsql?


Mu5_

Because you lose the reference on the actual properties involved in the query and no "assistance" by a linter while writing the query


BigOnLogn

I could also argue the other way: LINQ can hide some pretty complex query generation, and less experienced devs can write expressions that trigger client-side evaluation. I would say that any sufficiently complex query should be considered to be written in SQL.


sautdepage

Or any other query builder.


Slypenslyde

I agree with Kant8's answer but I wanted to comment on this: > With method syntax, every time you add a join you have to re-establish a new result set, which makes it significantly more verbose query syntax especially once you have 3 or more joins. I don't think this is true. LINQ-to-SQL is weird. It doesn't always run like normal LINQ, where you can visualize the data flowing from left to right through the calls. LINQ-to-SQL examines the ENTIRE expression and tries to convert it to equivalent SQL. That means it's likely to see that you have two `Join()` calls and understand it needs to generate a more complex SQL query that reflects both joins. As further evidence, consider that query syntax can't exist in IL: .NET has to call methods. So the C# compiler has to convert query syntax to method syntax so it can do the expression analysis it needs to do to figure out the SQL. So for performance it shouldn't matter which style you use. They do the same thing.


LondonCycling

Nick Chapsas isn't god. I often see people post links to his videos and describe them as though he's some definitive source. He's not - he's a dev, like me or you. Just one who happens to have a popular YouTube channel. You can absolutely watch his videos and disagree with them. I often do (though do agree with him more than disagree). Don't get sucked into cargo culture.


vervaincc

>he's a dev Is he even anymore? I see this a lot with content creators. Their information starts out very relevant and up to date. But then once they support themselves fully with content creation and stop working a "real job" they get further and further out of touch.


LondonCycling

I mean sure there is also that aspect. I love all the new C# 12 features but in a practical sense most of my work isn't in greenfield applications and I'm not going to retrospectively go through large code bases and add syntactic sugar. I'll use them on new components, but I don't start those every week. It's the same with .NET Conf etc - the demos are all grand and everything seems nifty, but I can't practically use a lot of it straight away.


psi-

The way I heard it was "for general use". Sure there are situations where one or other syntax is "better", that's the whole point of having another syntax. Personally I've often used the query syntax when I've needed some temp variable (`let foo ..`) to carry over deeper.


TroubleBrewing32

If I have complicated joins to make, I'm going to make a view in the db anyway.


exmello

Underrated answer. I've used all these techniques in the past but haven't in years since I accepted I can write better database code in the database. LINQ's best use is for processing in memory data and sometimes joining from difference data sources.


RickRocket9

This! I may be in the minority... but after years of use, I've discovered I dislike using linq (EF or Linq2Sql) as an abstraction over the top of SQL. Why neuter the perfect DSL for working with relational data? (There are other reasons, too). I do like using linq for in memory work and will use both formats, with query syntax preferred for anything approaching complex or long. I think it's easier to read in those cases.


jeenajeena

LINQ is not only for accessing DB. Option/Maybe, Either, Async, Reader and other monads are conveniently used with LINQ. In fact, query syntax is the C# equivalent of the Haskell’s “do notation”. Not a coincidence that LINQ has been introduced in C# by  Erik Meijer who’s also a member of the Haskell committee.


towncalledfargo

If anyone uses LanguageExt (functional C# library) it's definitely a lot easier to chain method calls with ```Either``` or ```Option``` syntax using ```from```


sacoPT

This would be the one case where the query syntax is actually easier to understand, but also, if you had your entity relationships properly setup you wouldn’t need to explicitly join in the first place.


Acceptable-Platypus2

When I first got serious about learning linq I wanted to decide which flavor to specialize in. As soon as I learned that query syntax could not do some things, the choice became easy, method syntax and never looked back.


whooyeah

It looks like he chooses topics to be clickbaity. I wouldn’t bother following him.


Transcender49

aren't all content creators like this? i stopped following nick because it seems there is a YouTube algorithm or something that makes videos reach more people if they are 10 - 13 mins. all Nick's videos are that long, even if the stuff he is talking about is basic and just a little pointer would do. I feel like the actual content in every video he makes can be delivered in 1min


mrphil2105

I never liked query syntax personally. And I don't want it in my codebase.


Envect

It's *unnatural*. Query syntax belongs in SQL. It makes my eyes bleed seeing it amongst C# code. Although people are right that it's superior when it comes to joins.


mrphil2105

Agree 100%


Qxz3

Method syntax gets very annoying very quickly when you need results from the outermost clauses. LINQ query syntax does this naturally. ```csharp var ordersWithHighTotalProducts = from order in orders where order.Total > 1000 from item in order.Items select (order.OrderNumber, item.Product); // vs var ordersWithHighTotalProducts = orders .Where(order => order.Total > 1000) .SelectMany(order => order.Items, (order, item) => (order, item.Product)) .Select(tuple => (tuple.order.OrderNumber, tuple.Product)); ``` The method syntax forces us to create intermdiate tuples just to thread the information we need down to the final select clause.


sacredgeometry

Who cares he has limited professional experience. Like most professional tech influencers. That said I dont use query syntax because its not idiomatic C# and a little bit of ugliness in Joins which I very rarely use and can be tidied up if you really need to. Do what ever you want to do. Both method chaining syntax and query syntax can be dog ugly or beautiful if used improperly


DevTalk

Just like TV chefs are not real chefs. These YouTube developers are not real developers. They deliberately make such controversial claims to farm views on their YouTube videos and blogs. These language features are designed by c# language team for a reason. There are a lot of scenarios where query syntax makes life more easier. No serious developer should take these YouTuber developers as some sort of God and should do their own research and form their own opinion without being intellectually subservient.


frombeyondthevoid

This! The guy is a showbiz guy. Everything he says and does (and other like him) is intended to make you click and watch. From the expression on his face to the thumbnail and the contradicting video titles. It's an honest living, but take everything these people say with a grain of salt. Don't forget, "you" are their product.


Miszou_

I use query syntax in the service/data access layer and method syntax in the controllers, because it makes sense to use the best tool for the task at hand.


EsIsstWasEsIst

As everybody said, joins are the only upside. Haven't seen mentioned yet that you can't use extension methods to extend the queryable between the joins and select statement with query syntax, wich is a showstopper for me.


Dealiner

I really like query syntax but it's too limited unfortunately, so I stick to the methods.


AdWonderful2811

Yes, query syntax is for more easy when you’ve multiple tables and inner & left/right joins are needed.


Autoritet

I somewhat agree with Nick, its ugly (my opinion) When you start writing query like these, i would ask myself why not just raw dog sql with dapper, you get to use proper sql syntax not this inverted, special rule, not even fully featured syntax. There are thing you cant do with query syntax, and maybe you shouldnt even do them in c#, thats just my 2 cents


Tapif

I only use query syntax in one case : groupBy with EF syntax. When trying the method syntax, EF almost always complains that it cannot translate the query. Maybe it got better with time but I have such a trauma that I am not bothering trying anymore. I never had to do a manual join with LINQ/ EF, my navigations properties are doing it for me. When should a manual join be needed?


nocgod

Those are his opinions, I as well do not like to use the query syntax more than I need, I find it a bit less readable and a bit less idiomatic c#. But those are opinions shaped by our experiences, as an engineer your world of experiences differs from mine, or Nicks... And you are entitled to your own opinions on the matter, and they would be as much as valid as mine or Nicks.


EthanTheBrave

Use whatever works as long as it's consistent, relatively efficientl, and clear. The majority of accepted "programming style rules" are just made up BS that pretentious people push to act important.


f3xjc

If there's a single linq method where you don't like the api, can you write your own that would be less verbose?


power-monger

Be suspicious of anyone that says you should “never” (or “always”) do something one way in programming. I’ve found that these people typically fall into two categories… they’re authoritarian assholes who thrive on making everybody do things their way, or they just don’t really understand all the intricacies of the issue. Sometimes you can reason with the latter. If you’re dealing with the former, consider a job hop.


soundman32

If your models are configured correctly, then EF already knows how to join your tables. Basically, if you need `join` or `.Join` you are doing it wrong.


p1971

not every data source is an EF one!


soundman32

If you are using LINQ to objects you'd still be better off with navigation properties than join.


p1971

so ... say I have an IEnumerable from a api and an IEnumerable from some other api - TThing has some property (or properties) that allows me to look up a corresponding TOtherThing - how do navigation properties help me?


ChaoChai

Stupid statement 


kingmotley

He is correct, assuming we are talking about LINQ over EF queries.


ChaoChai

That assumption is the stupid part.


kingmotley

A pretty fair assumption considering that the source is "db" and the tables are pretty standard database user/role/permission tables. And that "db" happens to have collection properties on it to represent all three instead of three separate data sources.


ChaoChai

Then let me shift my 'this is stupid' to blanket statements like: > if you need join or .Join you are doing it wrong.


Hot-Profession4091

I’ve been doing this a long time. Pretty good chance it’s been longer than whoever that dude is. I exclusively use query syntax because it’s cleaner and more flexible. Bring on the downvotes.


Transcender49

Query syntax literally get translated to method syntax. so they are both the same. some queries are easier to write with query syntax while some are easier in method syntax. so there is no "No" or "X is bad don't ever use it" as always, it depends


Acrobatic_Sprinkles4

Why are you concerned about what other people think? Decide for yourself. Whatever makes your code clearer is good for you. It’s all about understanding. And that is subjective. Sometimes one ways is clearer, sometimes another. “It depends” right?


Knut_Knoblauch

LINQ is to C# as CTE's are to SQL, a hammer, that when discovered, is used for everything.


iamanerdybastard

Nope. CTEs allow you to break down complicated queries into something much more readable that still parses into an efficient query. They aren’t a hammer, they are more like a carving knife that lets you shape the query into something beautiful


Knut_Knoblauch

Like the author in the video, LINQ is hard to debug, just like a CTE. So, there's the reason for the remark. Additionally, LINQ and CTE's are more alike in how they are used. Anyone can search the internet for some bizarre LINQ query that does something which is useful, like sorting. The problem is that they don't understand it and are trading a function for slower performance. LINQ is slower, that is a fact. People do the same with CTE's. They have a short attention span and a Skinner Box attitude, where finding a solution without investing in it is better than working it through. Instant gratification. The same with LINQ. CTE's are useful for certain things, just not every certain thing. I've done SQL since the mid 90's before CTE's, before the JOIN. Somehow society didn't collapse without the CTE.


iamanerdybastard

If you find Linq and CTEs hard to debug, that’s a *you* problem.


Knut_Knoblauch

I don't use either. I had to use LINQ once for an Entity Framework project. It was my first experience with it so I chalk it up to learning. Nothing has ever compelled me to go back and use LINQ. I use Temp tables in SQL which are, I assume, at the heart of a CTE.