EF Core: LINQ vs. Raw SQL - A Surprising Benchmark
I’ve been there. You’re staring at a dashboard in your multi-tenant app, and it’s crawling. The culprit is a query filtering across tens of thousands of records. Your first instinct? “LINQ is too slow. I’ll just write the raw SQL myself.”
It’s a tempting thought. But dropping down to raw SQL isn’t a simple performance switch. Get it wrong, and you could introduce a security hole or, ironically, make performance even worse. This exact scenario burned me once in production, and the fix wasn’t what I expected.
Let’s break down when to stick with LINQ and when (and how) to safely write your own SQL in EF Core.
First, The Big One: Security
If you take one thing away from this post, let it be this: never concatenate user input into a SQL string. SQL injection isn’t a textbook problem; it’s a real threat that I’ve seen take down production systems.
It’s easy to make this mistake, especially with C#’s slick string interpolation. This looks safe, right?
// DANGER: NEVER DO THIS.
var userId = Request.Query["userId"]; // e.g., "123"
var sql = $"SELECT * FROM Users WHERE Id = {userId}";
var users = await context.Users.FromSqlRaw(sql).ToListAsync();
This code is a wide-open door. An attacker can send 123; DROP TABLE Users; --
as the userId
, and boom, your user table is gone.
The critical gotcha is that standard C# string interpolation ($"..."
) does not protect you. It just …