views:

23

answers:

1

I'm following the fairly standard L2S repository pattern, using the following as one of the methods

public IEnumerable<T> GetAllByFilter(Func<T, bool> expression)
 {
     return _dataContext.GetTable<T>().Where(expression);
 }

I'm a bit miffed to see that the call to GetTable appears to literally get the table, with the Where expression presumably evaluated in-memory afterwards.

So a simple call like

var order = GetAllByFilter(o => o.OrderNumber == 1);

which should only ever return one record, is fetching the entire 50000 record database.

Is Linq normally this bad? Or am I missing something?

+2  A: 

Change:

public IEnumerable<T> GetAllByFilter(Func<T, bool> expression)
{
    return _dataContext.GetTable<T>().Where(expression);
}

To:

public IQueryable<T> GetAllByFilter(Expression<Func<T, bool>> expression)
{
    return _dataContext.GetTable<T>().Where(expression);
}

This will use Queryable (i.e. SQL) instead of Enumerable (i.e. local) and therefore will perform much better.

Kirk Woll
+1 Kirk. I see this issue a lot; in addition to the concept of deferred execution not seeming to be widely known, the difference between the extension methods behavior for IEnumerable and IQueryable (and the Expression<T> type) seems to be a nuance many are not aware of.
Andrew Barber
Thank you! I'd tried `IQueryable` but didn't know that you needed an `Expression` paramater to `Where`. Do you have a good link that explains this?
fearofawhackplanet
@fear, yeah, this surprised me too when I first learned about it. Not certain of the most convenient resource, but if you've never browsed the language specification, it's far more readable than you might expect. The link to it is: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=DFBF523C-F98C-4804-AFBD-459E846B268E. The relevent section is "4.6 Expression tree types". A good C# book (like C# In Depth) will also cover this territory well.
Kirk Woll