EPISODE · Sep 18, 2025 · 19 MIN
LINQ to SQL With EF Core Explained: Expression Trees, Query Provider, Caching & Why Your LINQ Becomes Weird SQL
from M365.FM - Modern work, security, and productivity with Microsoft 365 · host Mirko Peters - Founder of m365.fm, m365.show and m365con.net
Have you ever written a LINQ query that worked perfectly in C#, but when you checked the SQL it generated you wondered how it turned into that monster? In this episode, you’ll learn how expression trees control translation, how EF Core’s query provider decides what becomes SQL and what falls back to client‑side evaluation, and how caching quietly shapes performance and memory use. We also dig into null semantics and why queries that behave in LINQ to Objects can suddenly blow up—or slow down—once EF Core gets involved.WHAT REALLY HAPPENS WHEN YOU RUN A LINQ QUERYLINQ itself doesn’t know anything about SQL; it’s just C# calling methods. EF Core captures those calls as expression trees—object graphs that describe your query before anything is sent to the database—so nothing executes at the moment you type \Where\\ or \Select\\. We walk through how EF turns each clause into nodes (method calls, properties, constants), why that structure matters for translation, and how helper methods and complex expressions can make parts of your query “not SQL‑legal.” That’s the first place where behavior diverges from LINQ to Objects: in memory everything runs, but in EF Core unsupported patterns trigger errors or expensive client‑side evaluation.THE QUERY PROVIDER: GATEKEEPER BETWEEN LINQ AND SQLEF Core’s query provider acts like a gatekeeper, walking the expression tree and pattern‑matching which nodes it can translate into SQL and which it can’t. We explain why common patterns (Where, Select, OrderBy) map cleanly, while others (certain GroupBy scenarios, custom methods) either fail or fall back to in‑memory processing that silently pulls far too many rows. You’ll learn how to recognize when a query is being evaluated client‑side, why that often only shows up as performance pain in production, and why it’s better to get a hard error than a “working” query that drags your app under load.CACHING: EF CORE’S HIDDEN PERFORMANCE LEVEREvery time EF Core translates a query shape from an expression tree into an executable plan, it does real work—parsing, validating, and preparing SQL and materialization logic. We look at how EF Core caches these decisions so repeated queries don’t rebuild the pipeline every time, why parameterized shapes benefit most from this, and how small changes to your LINQ can accidentally defeat caching and hurt throughput. Combined with null‑handling rules and translation limits, this caching behavior explains why two queries that look almost identical in C# can feel very different in SQL Server under load.WHAT YOU’LL LEARNHow LINQ queries become expression trees and why that matters for EF Core translation.How EF Core’s query provider decides what can become SQL and when to fall back to client‑side evaluation.How caching of query shapes impacts performance and why tiny changes can break cache reuse.Why null semantics and helper methods can make LINQ behave differently in EF Core than in LINQ to Objects.THE CORE INSIGHTThe core insight of this episode is that EF Core isn’t a black box—it follows a predictable pipeline of expression trees, provider decisions, and cached plans. Once you understand that structure, “weird” SQL, sudden performance drops, and confusing null behavior stop looking like magic and start looking like architecture issues you can actually fix in your queries.WHO THIS EPISODE IS FOR.NET developers using LINQ with EF Core against SQL Server or Azure SQL.Backend engineers debugging slow or surprising SQL generated by their LINQ queries.Architects and tech leads who need to explain EF Core’s query pipeline to teams.ABOUT THE AUTHOR / HOSTMirko Peters is a Microsoft 365 and data platform consultant and host of the M365.FM podcast, helping organizations treat .NET, SQL Server, and their data layer as one integrated operating system instead of disconnected ORMs and databases. He works with teams running on Microsoft 365, Azure, and modern data stacks to design query, performance, and architecture patterns so LINQ, EF Core, and SQL work together predictably instead of producing surprise slowdowns in production.Become a supporter of this podcast: https://www.spreaker.com/podcast/m365-fm-modern-work-security-and-productivity-with-microsoft-365--6704921/support.
What this episode covers
Have you ever written a LINQ query that worked perfectly in C#, but when you checked the SQL it generated you wondered how it turned into that monster? In this episode, you’ll learn how expression trees control translation, how EF Core’s query provider decides what becomes SQL and what falls back to client‑side evaluation, and how caching quietly shapes performance and memory use. We also dig into null semantics and why queries that behave in LINQ to Objects can suddenly blow up—or slow down—once EF Core gets involved.WHAT REALLY HAPPENS WHEN YOU RUN A LINQ QUERYLINQ itself doesn’t know anything about SQL; it’s just C# calling methods. EF Core captures those calls as expression trees—object graphs that describe your query before anything is sent to the database—so nothing executes at the moment you type \Where\\ or \Select\\. We walk through how EF turns each clause into nodes (method calls, properties, constants), why that structure matters for translation, and how helper methods and complex expressions can make parts of your query “not SQL‑legal.” That’s the first place where behavior diverges from LINQ to Objects: in memory everything runs, but in EF Core unsupported patterns trigger errors or expensive client‑side evaluation.THE QUERY PROVIDER: GATEKEEPER BETWEEN LINQ AND SQLEF Core’s query provider acts like a gatekeeper, walking the expression tree and pattern‑matching which nodes it can translate into SQL and which it can’t. We explain why common patterns (Where, Select, OrderBy) map cleanly, while others (certain GroupBy scenarios, custom methods) either fail or fall back to in‑memory processing that silently pulls far too many rows. You’ll learn how to recognize when a query is being evaluated client‑side, why that often only shows up as performance pain in production, and why it’s better to get a hard error than a “working” query that drags your app under load.CACHING: EF CORE’S HIDDEN PERFORMANCE LEVEREvery time EF Core translates a query shape from an expression tree into an executable plan, it does real work—parsing, validating, and preparing SQL and materialization logic. We look at how EF Core caches these decisions so repeated queries don’t rebuild the pipeline every time, why parameterized shapes benefit most from this, and how small changes to your LINQ can accidentally defeat caching and hurt throughput. Combined with null‑handling rules and translation limits, this caching behavior explains why two queries that look almost identical in C# can feel very different in SQL Server under load.WHAT YOU’LL LEARNHow LINQ queries become expression trees and why that matters for EF Core translation.How EF Core’s query provider decides what can become SQL and when to fall back to client‑side evaluation.How caching of query shapes impacts performance and why tiny changes can break...
NOW PLAYING
LINQ to SQL With EF Core Explained: Expression Trees, Query Provider, Caching & Why Your LINQ Becomes Weird SQL
No transcript for this episode yet
Similar Episodes
Mar 26, 2026 ·1m
Mar 19, 2026 ·34m
Feb 18, 2026 ·11m
Feb 11, 2026 ·45m