1

I'm preparing data for a datatable in Linq2Sql

This code highlights as a 'Possible multiple enumeration of IEnumerable' (in Resharper)

// filtered is an IEnumerable or an IQueryable

var total = filtered.Count();

var displayed = filtered
                .Skip(param.iDisplayStart)
                .Take(param.iDisplayLength).ToList(); 

And I am 100% sure Resharper is right.

How do I rewrite this to avoid the warning

To clarify, I get that I can put a ToList on the end of filtered to only do one query to the Database eg.

 var filteredAndRun = filtered.ToList();

 var total = filteredAndRun.Count();

 var displayed = filteredAndRun
                .Skip(param.iDisplayStart)
                .Take(param.iDisplayLength).ToList(); 

but this brings back a ton more data than I want to transport over the network.

I'm expecting that I can't have my cake and eat it too. :(

Peter
  • 7,792
  • 9
  • 63
  • 94

2 Answers2

2

It sounds like you're more concerned with multiple enumeration of IQueryable<T> rather than IEnumerable<T>.

However, in your case, it doesn't matter.

The Count call should translate to a simple and very fast SQL count query. It's only the second query that actually brings back any records.

If it is an IEnumerable<T> then the data is in memory and it'll be super fast in any case.

I'd keep your code exactly the same as it is and only worry about performance tuning when you discover you have a significant performance issue. :-)

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Yep, it's more of a problem for me that the database is hit twice. I can't see another way of doing this...although in this particular case the data won't be changing so I could run the count once rather than doing it every time I need a new page of data. – Peter May 21 '12 at 23:33
0

You could also do something like

count = 0;
displayed = new List();
iDisplayStop = param.iDisplayStart + param.iDisplayLength;
foreach (element in filteredAndRun) {
    ++count;
    if ((count < param.iDisplayStart) || (count > iDisplayStop))
          continue;
    displayed.Add(element);
}

That's pseudocode, obviously, and I might be off-by-one in the edge conditions, but that algorithm gets you the count with only a single iteration and you have the list of displayed items only at the end.

srm
  • 3,062
  • 16
  • 30