30.06.2013 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!