Question: **Why does forcing materialization using `ToList()` make my query orders of magnitude faster when, if anything, it should do the exact opposite?**

1) Calling `First()` immediately

```
    // "Context" is an Entity Framework DB-first model

    var query = from x in Context.Users
                where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
                select x;

    var User = query.First();

    //  ** The above takes 30+ seconds to run **

```

2) Calling `First()` *after* calling `ToList()`:

```
    var query = from x in Context.Users
                where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
                select x;

    var User = query.ToList().First();     // Added ToList() before First()

    // ** Now it takes < 1 second to run! **

```

Update and Resolution
=====================

After getting the generated SQL, the only difference is, as expected, the addition of `TOP (1)` in the first query. As [Andyz Smith](https://stackoverflow.com/a/18361548/110549) says in his answer below, the root cause is that the SQL Server optimizer, in this particular case, chooses a worse execution plan when `TOP (1)` is added. Thus the problem has nothing to do with LINQ (which did the right thing by adding `TOP (1)`) and everything to do with the idiosyncrasies of SQL Server.

Answer: 
The SQL won't be the same as Linq is [lazy loading](https://stackoverflow.com/questions/36274/what-is-lazy-loading). So your call to `.ToList()` will force .Net to evaluate the expression, then in memory select the `first()` item. 

Where as the other option should add `top 1` into the SQL

E.G.

```
var query = from x in Context.Users
                where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
                select x;

 //SQL executed here
 var User = query.First();

```

and

```
var query = from x in Context.Users
                where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
                select x;

 //SQL executed here!
 var list = query.ToList();
 var User = query.First();

```

As below, the first query **should be faster**! I would suggest doing a [SQL profiler](http://technet.microsoft.com/en-us/library/ms181091.aspx) to see what's going on. The speed of the queries will depend on your data structure, number of records, indexes, etc.

The timing of your test will alter the results also. As a couple of people have mentioned in comments, the first time you hit EF it needs to initialise and load the metadata. so if you run these together, the first one should always be slow.

Here's some more info on EF [performance considerations](http://msdn.microsoft.com/en-us/library/cc853327%28v=vs.110%29.aspx)

notice the line:

> 
> Model and mapping metadata used by the Entity Framework is loaded into
>  a MetadataWorkspace. This metadata is cached globally and is available
>  to other instances of ObjectContext in the same application domain.
> 
> 
> 

&

> 
> Because an open connection to the database consumes a valuable
>  resource, the Entity Framework opens and closes the database
>  connection only as needed. You can also explicitly open the
>  connection. For more information, see Managing Connections and
>  Transactions in the Entity Framework.
> 
> 
>
So, the optimizer chooses a bad way to run the query.

Since you can't add optimizer hints to the SQL to force the optimizer to choose a better plan I see two options.

1. Add a covering index/indexed view **on all the columns that are retrieved/included in the select** Pretty ludicrous, but I think it will work, because that index will make it easy peasy for the optimizer to choose a better plan.
2. Always prematurely materialize queries that include First or Last or Take.  Dangerous because as the data gets larger the break even point between pulling all the data locally and doing the First()  and doing the query with Top on the server is going to change.

<http://geekswithblogs.net/Martinez/archive/2013/01/30/why-sql-top-may-slow-down-your-query-and-how.aspx>

<https://groups.google.com/forum/m/#!topic/microsoft.public.sqlserver.server/L2USxkyV1uw>

<http://connect.microsoft.com/SQLServer/feedback/details/781990/top-1-is-not-considered-as-a-factor-for-query-optimization>

[TOP slows down query](https://stackoverflow.com/questions/6681841/top-slows-down-query)

[Why does TOP or SET ROWCOUNT make my query so slow?](https://stackoverflow.com/questions/1759797/why-does-top-or-set-rowcount-make-my-query-so-slow)