Disclaimer!
This post is a little bit ridiculous and over the top but I'd be doing injustice if I do not share my thoughts on how the journey of learning something new feels like. But if you're in a rush, just scroll to the snippet at the bottom
So here's the thing. Years ago, when I had just started programming, as part of my degree, I hated C#. I didn't want anything to do with any project related to Microsoft related tech. Here's the rationale behind this (it's a dumb rationale) Why does C# have a 'C' in its name but looks almost exactly like Java? I also believed that a good programmer must know Java, C/C++, PHP for server programming, and Python just to prove you're smart. I swear this is a phase that I literally went through.
This was because when you've just started coding, for some reason there's this notion of being defined by the programming languages you know and the libraries you use. I'm sure that was greatly influenced by the "Top 10 best languages to learn in 201X" or "Language X is dead, here's why", even "Programming languages used by Facebook" articles that I actively looked for! just so that I don't get left behind in the industry.
Of course, a lot changed in the way I view tech and my career but what I felt about C# or anything related to it never changed, until about 6-7 months ago. See, at work, they use a shit ton of .NET (or dotnet. I'm still getting the hang of this) so I'm learning it now. A few months ago, I completed a 'Basics for beginners' udemy course. It was fine I guessπ but learned a lot of cool stuff π€
Now I'm creating a project so that I learn more of this freaky stuff. Enter .NET Core 3! The most overwhelming piece of framework I've ever encountered (this year. I have to be clear on this). I have never given up so many times but come back to try again, in just a single week, ever for any project that I ever started to learn. When I finally got my thingie to give me a token for authentication, after days and nights of struggle, I ran the most satisfyingly powerful git command known to mankind
git commit -m 'Initial commit'
I was happy. Then I had my supper while rereading up on what I've implemented and that's when I saw it
The masterpiece
private User GetUserByToken(string token)
{
var user = (from u in _context.Users
join t in _context.Tokens
on u.Id equals t.UserId
where t.Body == token
select u).SingleOrDefault();
return user;
}
It's beautiful isn't it? I thought so too
I mean do you understand that the last time I saw something this cool was when I saw JSX for the first time, which looked so confusing but really not so trivial after some time of use. My brain doesn't have to context switch between application code and database scripts but the thing just works seamlessly. And the syntax highlighting plus the IntelliSense! I am stunned.
If you're reading this and you do not understand WTF is going on here, it's okay, it's not your time yet. But later on in your life, you will see what I saw and you'll say "shit, that dude on dev.to wrote a weird post about this feeling I'm feeling right now".

Oldest comments (64)
Great! Now try lambda expression, you will be happier:)
I did π it looks way better if you're working on a single table
You can use navigation properties and lambda to improve your code.
Something like:
public class User
{
public virtual Token Token { get; set; }
}
And then:
_context.Users.SingleOfDefault(u => u.Token.Body == Token);
Ok, this actually looks cleaner and more concise. I'm assuming from this that the virtual property relation to users is setup automatically because both entities exist in one context. I'm puzzled by how this really works
Here's another strange thing I'm picking up from this snippet, the fact that the property name and its type can just be exactly the same without C# complaining. I've been experimenting areas where such is possible.
public virtual Token Token;Wait till you see dynamic LINQ =)
Or manually build expression trees haha :-)
Use lazy loading proxy from
Microsoft.EntityFrameworkCore.Proxiespackage, so you can get better sleepI'll look this up! Thanks
Lazy loading navigations can easily lead to accidental N+1 queries. You can explicitly include navigations with
DbSet<>.Include.Here is your example written using an async method and lambda expression syntax:
private async Task<User> GetUserByTokenAsync(string token) => await _context.Users
.Join(_context.Tokens.Where(t => t.Body == token), u => u.Id, t => t.UserId, (u, t) => u)
.SingleOrDefaultAsync();
Note: you will need to include additional namespaces for the async extension methods on IQueryable<> and for Task<>
Drop the async and await keywords for better performance.
At some point, I'm looking forward to benchmarking the alternatives i.e. Fluent vs Lambda, Async vs Sync. I'm certain there's no one answer for every use case
Fluent translates to the same underlying Linq statements and concequently the same generated SQL. Note: The await keyword can be used in front of the parentheses.
Async code frees up the thread to do other things while it's waiting for the slower database network roundtrip. You are trading a small setup cost for starting the state machine handling the async processing, but that's it.
So basically async statements are useful for performance in situations where the data being processed is rather large
I agree that using the Async flavor of the SingleOrDefault is generally the preferred way as it improves massively the amount of load a single server can absorb. My comment was simply that the proposed method does not need to be async (contain the keyword async in the signature) as there is no need to await tasks and execute continuations within the function. So, basically, you can directly return the Task returned by SingleOrDefaultAsync without awaiting it as the caller will await it.
@Beautus S Gumede on "So basically async statements are useful for performance in situations where the data being processed is rather large"
(Not seeing proper "Reply" function on mobile)
That's one example where async is advantageous, and there are many, and it gets complicated pretty quick. I would recomend doing a deep dive on Asynchronous and Threading, but know that they are two very different subjects (although their impacts on your code can appear similar).
There's a pretty common analogy used to explain threading involving a chef/cook that I find to be a good foundation for internalizing the concept. Examples are all over Google for that. This article gives you a reasonable overview with some good detail, IMO: medium.com/swift-india/concurrency...
Happy coding!
@Beautus S Gumede In a highly performant scalable web app, async/await allows .NET to momentarily give the underlying thread to a different incoming request while waiting on IO (such as a database call). It makes .NET prolly the most scalable stack out there when done right. NodeJS does similar things with its singlethreaded event loop.
This is much better understandable I think
Yeah... LINQ is solid stuff. Had a dev on my team give the same reaction a few weeks back.
LINQ is your next thrill
I never enjoyed anything like this in a long time. I just had to write about it. Flutter almost gave me a similar vibe but it wasn't that thrilling
EDIT: Jsx did!
LINQ, like SQL, is declarative.
It's interesting that I didn't' use the term 'declarative' but now that you've mentioned it, everything makes sense. I like declarative code :D
Roll with it. Read 'T-SQL Fundamentals, Third Edition' by Itzik Ben-Gan. Work through all the examples. You'll see why "SELECT" really belongs after "FROM" and "WHERE" (LINQ knows!). Find a good LINQ resource and work through more examples (LINQ to this, LINQ to that...). Don't worry about the lambda expressions underpinning LINQ syntactic sugar at this time. Microsoft has a fine offering. Visual Studio is the best IDE on the market. DOT NET "Core" is platform independent. For Web, perhaps check out angular.io (a Google framework) underpinned by TypeScript language (the "C# guy" invented TypeScript). Angular is organized, TypeScript is awesome, and it all downcompiles into the correct JavaScript for the device requesting your "stuff." There are dollar bills for your bank account on the Microsoft train. A lot of the other stuff is budget busting, shifting sand. In my experience.
I 100% agree that SQL got select wrong, and it should be at the end!
As for VS being the best IDE, I honestly find using Kotlin and IntelliJ Idea more pleasant.
I really enjoy your writing style. Followed!
Thanks a lot, man. I appreciate that a lot. I try to make it as relatable and conversational as much as possible.
The next step up from this is to combine this with webapi odata, that way the framework generated this sort of linq expression for you from a URL.
The irony here is the discovery .net core 3 and the EF core libs that make this possible are right now in a worse state than the ef6 and .net 4.x stuff regular .net people just migrated from.
Give it a couple years though and this will be special under .net 5 when you start notice it's literally write once, run anywhere.
If you like that, check out rx.net reactive extensions for linq