An IAsyncCursor can only be enumerated once

Smith
Smith
None
2568 Points
74 Posts

I am trying to update IEnumerable list see code snapshot below:

private IApiDataDetails ApiGetDataMembers(string dsName, string dsId, bool defaultDs = false)
{
ApiDataDetails apiDs = new ApiDataDetails();
apiDs.Name = dsName;
apiDs.Experiences = _dsRepo.GetApiDataMembers <IApiExperience, ApiExperience>(dsId,..);
foreach (var ex in apiDs.Experiences)
{
ex.Foo = null;
ex.FooDate = DateTime.Now;
}
return apiDs;
}

But getting error when json response generated at api action:

{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"An IAsyncCursor can only be enumerated once.","ExceptionType":"System.InvalidOperationException","StackTrace":"   at MongoDB.Driver.Core.Operations.AsyncCursorEnumerableOneTimeAdapter`1.GetEnumerator()\r\n   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"}}

Have anyone any idea for this error ?

Views: 13870
Total Answered: 2
Total Marked As Answer: 0
Posted On: 19-Dec-2017 04:53

Share:   fb twitter linkedin
Answers
Jak
Jak
Member
858 Points
132 Posts
         

Try explicitly enumerating the results by calling ToList().

Change

foreach (var ex in apiDs.Experiences)

to

foreach (var ex in apiDs.Experiences.ToList())
Posted On: 19-Dec-2017 05:12
Not working. getting same error
 - Smith  20-Dec-2017 05:07
Priya
Priya
Participant
936 Points
28 Posts
         

Add .ToList() before for-each loop:

apiDs.Experiences = _dsRepo.GetApiDataMembers<IApiExperience, ApiExperience>(dsId,..).ToList();

Full code:

private IApiDataDetails ApiGetDataMembers(string dsName, string dsId, bool defaultDs = false)
{
ApiDataDetails apiDs = new ApiDataDetails();
apiDs.Name = dsName;
apiDs.Experiences = _dsRepo.GetApiDataMembers<IApiExperience, ApiExperience>(dsId,..).ToList();
foreach (var ex in apiDs.Experiences)
{
ex.Foo = null;
ex.FooDate = DateTime.Now;
}
return apiDs;
}
Posted On: 20-Dec-2017 05:18
That worked! Can you explain why it works?
 - Smith  20-Dec-2017 05:28
it works because using ToList you are retrieving ALL results from the db in this list, from now on linq methods aren't going to work on the database.
 - Priya  20-Dec-2017 05:43
The main cause .ToList() works is that when you use an IEnumerable, the collection is iterated in a lazy way. In this case, each time the foreach loop gets an item, the query retrieves the item from your db or whatever you are using, if you want to iterate again it wont be able to redo the query. When you use .ToList(), all the items in the IEnumerable are processed and saved as a list. Then you can use the created list as many times as you want.
 - Brian  20-Dec-2017 05:45
 Log In to Chat