I have a data access class that took me a while to get working. For my app, I need to get different types of SQL Server tables where the WHERE clause only differs by the column name: some columns are read_time, others are ReadTime, and others are LastModifiedTime. So I thought I'd pass in the WHERE clause so I didn't need to create a new method for 50 different tables. It looks simple, and it works, but I don't understand something.
This method, with Expression<> as the parameter, works:
internal List<T> GetObjectsGreaterThanReadTime<T>(Expression<Func<T, bool>> whereClause) where T : class
{
Table<T> table = this.Database.GetTable<T>();
IEnumerable<T> objects = table.Where(whereClause);
return objects.ToList();
}
Now, I was trying it this way (below) for a while, and it would just hang on the last line (ToList()). First, why would this compile? I mean, why can Expression and Func be used interchangeably as a parameter? Then, why does Expression work, and the Func version just hangs?
Note: The only difference between the above method and this one is the method parameter (Expression vs. Func).
internal List<T> GetObjectsGreaterThanReadTime<T>(Func<T, bool> whereClause) where T : class
{
Table<T> table = this.Database.GetTable<T>();
IEnumerable<T> objects = table.Where(whereClause);
return objects.ToList();
}
The Expression version calls Queryable.Where
which generates an expression tree, which (when enumerated by ToList
) is translated to sql and executed on the database server. Presumably, the database server will avail itself of an index based on the filter criteria, to avoid reading the whole table.
The Func version calls Enumerable.Where
which (when enumerated by ToList
) loads the whole table (what you perceive as a hang) and then runs the filter criteria against the in-memory objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With