MongoDB: удаление курсора

7

Выдержка из драйвера С#:

It is important that a cursor cleanly release any resources it holds. The key to guaranteeing this is to make sure the Dispose method of the enumerator is called. The foreach statement and the LINQ extension methods all guarantee that Dispose will be called. Only if you enumerate the cursor manually are you responsible for calling Dispose.

Курсор "res", созданный при вызове:

var res = images.Find(query).SetFields(fb).SetLimit(1);

не имеет метода Dispose. Как я могу избавиться от него?

Теги:
mongodb-.net-driver

2 ответа

8
Лучший ответ

Запрос возвращает MongoCursor<BsonDocument>, который не реализует IDisposable, поэтому вы не можете использовать его в используемом блоке.

Важным моментом является то, что курсор перечислитель должен располагаться, а не сам курсор, поэтому, если вы использовали курсор IEnumerator<BsonDocument> напрямую, чтобы перебрать курсор, тогда вам нужно будет его утилизировать, вот так:

using (var iterator = images.Find(query).SetLimit(1).GetEnumerator())
{
    while (iterator.MoveNext())
    {
        var bsonDoc = iterator.Current;
        // do something with bsonDoc
    }
}

Тем не менее, вы, вероятно, никогда не сделаете этого, и вместо этого используйте цикл foreach. Когда перечислитель реализует IDisposable, как это делает, цикл с использованием foreach гарантирует его метод Dispose() будет вызван независимо от того, как цикл завершается.

Следовательно, такой цикл без явного распоряжения безопасен:

foreach (var bsonDocs in images.Find(query).SetLimit(1))
{
    // do something with bsonDoc                
}

Как оценивает запрос с Enumerable.ToList <T> , который использует цикл foreach за кулисами:

var list = images.Find(query).SetLimit(1).ToList();
  • 0
    Как насчет вызова FirstOrDefault () вместо ToList () - это гарантирует вызов Dispose для перечислителя? Потому что это то, как я использую это, и я хочу убедиться, что я использую это правильно.
  • 0
    Да, это тоже хорошо, он делает это: using (var enumerator = source.GetEnumerator()) { if (enumerator.MoveNext()) return enumerator.Current; }
Показать ещё 1 комментарий
3

Вам не нужно вызывать Dispose на курсоре (на самом деле у MongoCursor даже нет метода Dispose). Что вам нужно сделать, так это вызвать Dispose в перечислителе, возвращаемом методом GetEnumerator MongoCursor. Это происходит автоматически, когда вы используете оператор foreach или любой из методов LINQ, которые перебирают IEnumerable. Поэтому, если вы не вызываете GetEnumerator самостоятельно, вам не нужно беспокоиться о том, что вы выбрали Dispose.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню