3

Possible Duplicate:
The query results cannot be enumerated more than once?

I am using entity framework to select and return a group of entities form my database using a stored procedure.

var results = dataContext.loadData(testargument);

I want to count this returned set (to make sure only 1 record is returned and then take the first item in this list.

if(results.Count() == 1)
{
    ReturnedEntity entity = results.First();
}

However when I do this call I get the error "The result of a query cannot be enumerated more than once." Does anyone know how I can do this correctly? I assume that calling the Count() method is changing the data and am not sure if I need to put it back into a list before calling the first() method. I have tried results.ToList().First() but get the same error.

In addition I notice that if I call the First() method on an empty set I get an error which is why I am trying to make sure there is only 1 record returned.

Community
  • 1
  • 1
JBone
  • 3,163
  • 11
  • 36
  • 47
  • If you read up on deferred execution this should make a lot more sense: http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx – Richard Ev Apr 23 '12 at 16:35

6 Answers6

3

You can avoid this problem using ToList(). Becuase then when you have the list loaded in your memory you can do whatever you want. But I reccomend you use FirstOrDefault().

var results = dataContext.loadData(testargument).ToList();

And

ReturnedEntity entity = results.FirstOrDefault();

Or

if(results.Length == 1)
    ReturnedEntity entity = results.First();
Omar
  • 16,329
  • 10
  • 48
  • 66
  • FirstOrDefault() isn't the better approach. It just fits more often. I would use First when I know or expect the sequence to have at least one element. In other words, when it is an exceptional occurence when the sequence is empty. – Michael Schnerring Apr 23 '12 at 18:20
  • The OP wants to ensure that just one result is returned, not one or more. Therefore, `Single` is more appropriate. – Jodrell Apr 24 '12 at 08:18
0

ReturnedEntity entity = results.First();

if (entity != null)

0

Try calling .ToList() before getting the count, as this will also enumerate the results.

var resultList = results.ToList();
if(resultList.Count == 1)
{
    ReturnedEntity entity = resultList.First();
}
Jay
  • 56,361
  • 10
  • 99
  • 123
  • 1
    works but it may be faster to use the index accessor on a `List` , i.e. `resultList[0]` (only may) – Jodrell Apr 23 '12 at 16:26
0
var resultList = results.ToList();
if(resultList.Count == 1)
{
    ReturnedEntity entity = resultList.First();
}
Allison Steranko
  • 237
  • 2
  • 11
0

IEnumerable does not support this. This is by design. IEnumerable uses lazy evaluation to get the elements you ask for just before you need them.

If you want to know the number of items without iterating over them you can use IList<T>, it has a Count property.

Michael Schnerring
  • 3,584
  • 4
  • 23
  • 53
-1

I think that

try
{
    var result = dataContext.loadData(testargument).Single()
}
catch (InvalidOperationException)
{
    // Oops not a single result
}

is a better approach, if getting more or less than one result is exceptional. If more or less than one result occurs in normal execution you could do

var result = dataContext.loadData(testargument).SingleOrDefault()

if (result != null)
{
    // Continue as usual
}
else
{
   // Oops, not a single result
}

If you will make repeated use of the set that you could use the ToList extension,

var results = dataContext.loadData(testargument).ToList(); 

if(results.Count == 1) 
{     
    ReturnedEntity entity = results[0];
}
else
{
    // Oops, not a single result
}

IList supports multiple enumerations, has a Count property and an index accessor, IEnumerable does not.

Jodrell
  • 34,946
  • 5
  • 87
  • 124