1

I'm new to C# and LINQ, but the latter is pretty cool. Except I can't figure out what is going on here:

I have the following piece of code, which runs as expected; it sorts and selects the top 100 records:

IEnumerable<workerLog> query =
    (from record in _gzClasses.workerLogs                
    orderby record.workerID, record.timeStamp ascending                
    select record).Take(100);

foreach(var record in query)
{
    Console.WriteLine(record.timeInSession.ToString());
}

but when I do the following, the same lines print, but then the program hangs a bit and a SQLException is thrown saying the server timed out.

IEnumerable<workerLog> query =
    from record in _gzClasses.workerLogs                
    orderby record.workerID, record.timeStamp ascending                
    select record;

foreach(var record in query.Take(100))
{
    Console.WriteLine(record.timeInSession.ToString());
}

What in the world is the difference here? Does it have something to do with the way LINQ queries are executed? Coming from the Java world, it makes no sense.

4

1 に答える 1

3

Here is the mistake:

IEnumerable<workerLog> query =

By forcing it to IEnumerable<WorkerLog>, you have broken "composition", which means SQL server thinks you have asked for all the data, and at the receiver you will choose to only care about the first 100 rows. If you use IQueryable<WorkerLog> instead (or just var), then it can "compose" the Take(100) into the SQL and issue:

select top 100 ...

Note that in the first example, you only force it to IEnumerable<WorkerLog> after it has composed, so that works ok.... ish.

Basically, IQueryable<T> is the composable API that makes interesting TSQL from multiple operations. IEnumerable<T> is LINQ-to-Objects, which does the filtering / etc in c# rather than in SQL.

于 2012-08-02T22:21:08.483 に答える