Under the Hood of .NET Memory Management - Simple Talk
Under the Hood of .NET Memory Management - Simple Talk
Under the Hood of .NET Memory Management - Simple Talk
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Chapter 5: Application-Specific Problems<br />
With such a method, it seems natural to rewrite our original query as:<br />
Order[] pastDueAccounts = null;<br />
using (var context = new Context())<br />
{<br />
pastDueAccounts = context.Accounts<br />
.Where(account => PastDueAccount(account))<br />
.ToArray();<br />
}<br />
Listing 5.10: Rewriting <strong>the</strong> original LINQ to Entity Framework call.<br />
This logic is actually incorrect, but it may not be caught until after an application has<br />
been deployed and <strong>the</strong> database has had time to accumulate data. Let me explain why.<br />
With <strong>the</strong> original method, <strong>the</strong> compiler generated an expression tree and <strong>the</strong> database<br />
was queried for a limited amount <strong>of</strong> data. On <strong>the</strong> o<strong>the</strong>r hand, <strong>the</strong> refactored example<br />
pulls all <strong>of</strong> <strong>the</strong> orders from <strong>the</strong> database and <strong>the</strong>n filters <strong>the</strong>m in memory. The SQL that<br />
is generated will actually exclude <strong>the</strong> filtering restrictions, which will not be interpreted<br />
until after <strong>the</strong> SQL is run and <strong>the</strong> results returned.<br />
Instead <strong>of</strong> having <strong>the</strong> filter use indexes in <strong>the</strong> database and call up a small subset <strong>of</strong> <strong>the</strong><br />
data, no indexes will be used, and <strong>the</strong> entire contents <strong>of</strong> <strong>the</strong> table will be retrieved. For as<br />
long as <strong>the</strong> database has a small number <strong>of</strong> records, this will not cause a problem, but it<br />
will quickly cause substantial problems as <strong>the</strong> database volume grows.<br />
Why do we get this behavior? The compiler implicitly converts lambda expressions to<br />
ei<strong>the</strong>r expression trees or delegates, depending on <strong>the</strong> context in which <strong>the</strong>y are defined,<br />
but named methods are not converted to expression trees. They <strong>the</strong>refore don't match<br />
any <strong>of</strong> <strong>the</strong> extension methods for IQueryable, and are not incorporated into <strong>the</strong><br />
SQL that is sent to <strong>the</strong> database. Instead, <strong>the</strong>y are treated as delegates and passed to<br />
IEnumerable, and <strong>the</strong> delegate operates on <strong>the</strong> objects returned from <strong>the</strong> SQL call.<br />
158