Search code examples
c#entity-frameworklinqskip-take

Trouble getting total count using .Take() and .Skip()


I'm having some trouble implementing some paging using Linq and I've read the various questions (this and this for example) on here but I'm still getting the error;

System.InvalidOperationException: The result of a query cannot be enumerated more than once.

My (slightly obfuscated) code is;

public List<Thing> GetThings(ObjectParameter[] params, int count, int pageIndex)
{
    var things = from t in Context.ExecuteFunction<Something>("function", params)
                 select new Thing
                 {
                     ID = t.ID
                 });

    var pagedThings = things;

    if (pageIndex == 0)
        pagedThings = things.Take(count);
    else if (pageIndex > 0)
        pagedThings = things.Skip(count * pageIndex).Take(count);

    var countOfThings = things.Count();

    return pagedThings.ToList();
}

As soon as the final .ToList() is called, the error is thrown but I can't see why - are the calls to things.Count() and pagedThings.ToList() enumerating the same thing?

Edit: I'm using Entity Framework if that makes any difference


Solution

  • As it happens, ExecuteFunction causes the enumeration to occur immediately, ultimately meaning the code could be re-ordered and the copying of the list was not required - it now looks like the below

    public ThingObjects GetThings(ObjectParameter[] params, int count, int pageIndex)
    {
        var things = from t in Context.ExecuteFunction<Something>("function", params)
                 select new Thing
                 {
                     ID = t.ID
                 }).ToList();
    
        var countOfThings = things.Count;
    
        if (pageIndex >= 0)
            things = things.Skip(count * pageIndex).Take(count);
    
        return new ThingObjects(things, countOfThings);
    }