public IEnumerator <TDocument> Execute(IConnectionProvider connectionProvider) { MongoReplyMessage <TDocument> reply = null; try { var count = 0; var limit = (_limit >= 0) ? _limit : -_limit; reply = GetFirstBatch(connectionProvider); foreach (var document in reply.Documents) { if (limit != 0 && count == limit) { yield break; } yield return(document); count++; } while (reply.CursorId != 0) { reply = GetNextBatch(connectionProvider, reply.CursorId); foreach (var document in reply.Documents) { if (limit != 0 && count == limit) { yield break; } yield return(document); count++; } if (reply.CursorId != 0 && (_flags & QueryFlags.TailableCursor) != 0) { if ((reply.ResponseFlags & ResponseFlags.AwaitCapable) == 0) { Thread.Sleep(TimeSpan.FromMilliseconds(100)); } } } } finally { if (reply != null && reply.CursorId != 0) { try { KillCursor(connectionProvider, reply.CursorId); } catch { // don't throw any exceptions from the finally block } } } }
/// <summary> /// Moves to the next result and returns true if another result is available. /// </summary> /// <returns>True if another result is available.</returns> public bool MoveNext() { if (disposed) { throw new ObjectDisposedException("MongoCursorEnumerator"); } if (done) { // normally once MoveNext returns false the enumerator is done and MoveNext will return false forever after that // but for a tailable cursor MoveNext can return false for awhile and eventually return true again once new data arrives // so a tailable cursor is never really done (at least while there is still an open cursor) if ((cursor.Flags & QueryFlags.TailableCursor) != 0 && openCursorId != 0) { done = false; } else { return(false); } } if (!started) { reply = GetFirst(); if (reply.Documents.Count == 0) { reply = null; done = true; return(false); } replyIndex = -1; started = true; } if (positiveLimit != 0 && count == positiveLimit) { KillCursor(); // early exit reply = null; done = true; return(false); } // reply would only be null if the cursor is tailable and temporarily ran out of documents if (reply != null && replyIndex < reply.Documents.Count - 1) { replyIndex++; // move to next document in the current reply } else { if (openCursorId != 0) { reply = GetMore(); if (reply.Documents.Count == 0) { reply = null; done = true; return(false); } replyIndex = 0; } else { reply = null; done = true; return(false); } } count++; return(true); }