tags:

views:

73

answers:

1

I have a query that contains about 10 joins. Using a List View and Linq Data Source it pages fine against SQL2008 but fails to produce the correct result when run against SQL2000. No exception is thrown but the results are clearly out of order and at times, the same page is returned. Reading through the LINQ Docs, paging against queries wiht joins are not supported on SQL2000. Enough said although I would have expected an exception.

I am unable to move the data off SQL2000 right now. The solution is to do a full query and then perform memory based paging.

protected void LinqDataSourceMain_Selecting(object sender,
    LinqDataSourceSelectEventArgs e)
{
    // var query = myquery with join...
    e.Result = query.ToList();
}

Now the question is: Is it more efficient to invoke ToList() or ToArray() ?

AsEnumerable() does not fix the issue. Looking at the extension method with Reflector, it simply returns the 'source' so this makes sense to me.

e.Result = query.AsEnumerable();
public static IEnumerable<TSource> AsEnumerable<TSource>(
    this IEnumerable<TSource> source)
{
    return source;
}

However, would the following be more efficient than either ToList() or ToArray()? It does work and it does defer the execution.

e.Result = query.ToEnumerable();

public static IEnumerable<TSource> ToEnumerable<TSource>(
    this IEnumerable<TSource> source)
{
    foreach (var item in source)
        yield return item;
}
+3  A: 

ToList() will be more efficient than ToArray() because it doesn't need to do the final copy from an oversized buffer to a fixed-sized array.

If you're going to do in-memory paging, you don't want deferred execution (IMO) because you need to get the count of items, and random access. You don't want to have to re-execute the query each time.

Jon Skeet
Thanks. I will need to requery every time as this is a web app and I really don't want to store the result in a temp location such as Session. Still on the fence with deferred execution? Mybe splitting hairs? In the end, I should be able to move off of sql 2k but not right now.
Andrew Robinson
How are you going to work out the number of pages to display, out of interest? The fact that the results are out of order suggests you're going to have problems whatever you do - unless you can get the sort order consistent, you can't possibly page sensibly unless I'm missing something.
Jon Skeet
Paging and sorting works fine when I return a List. It fails when I return an IQueryable. With IQ, the first page displays correctly but things then fall appart from there. Looking at the SQL profiler, the SQL is really nasty. Sub-query over sub-query over sub-query over joins, etc.
Andrew Robinson
The generated SQL against SQL 2008 is very clean. Guessing that by deferring execution in the LDS_Selecting event, it isn't being deferred very long. Even with paging and deferred execution the full query is still run against SQL. Just wondering if it is better to deffere event for a brief time?
Andrew Robinson
Jon, different approach to the answer. The sql trace is identical for query.ToList(); or query.ToEnumerable(); Is ToEnumerable() more efficient simply in that it doesn't allocate a list just as list is more efficient than ToArray? Disregard the deferred execution part.
Andrew Robinson
The difference isn't really going to be between deferred execution and immediate execution, because you'll be using it so soon. The difference is going to be between streaming the results and buffering the results.
Jon Skeet
I'm not sure, but I wouldn't be surprised if LINQ to SQL buffered the results in memory anyway before returning any of them.
Jon Skeet
I did some rough benchmarks and ToList is faster than my method over an anonymouse type. When working with an IEnum<int>, ToArray wins.
Andrew Robinson