Как сделать findAll в новом драйвере mongo C# и сделать его синхронным


Я использовал официальный драйвер C#, чтобы сделать FindAll и обновился до нового драйвера 2.0. FindAll устарел и заменен на Find. Я пытаюсь преобразовать простой метод, который возвращает мне список Class1. Не могу найти реалистичный пример использования POCO в своей документации

var collection = database.GetCollection<ClassA>(Collection.MsgContentColName); return collection.FindAll().ToList();

Может кто-нибудь помочь мне преобразовать драйвер 2.0 и вернуть список, а не задачу?

5 21

5 ответов:

Вы можете сделать это, чтобы достичь того же с помощью драйвера 2.0,

var collection = database.GetCollection<ClassA>(Collection.MsgContentColName);
var doc = collection.Find(filter).ToListAsync();
doc.Wait();
return doc.Result;

Правка:

Они решили добавить обратно синхронную поддержку (хотя асинхронность все еще предпочтительнее для операций ввода-вывода), так что вы можете просто использовать:

var list = collection.Find(_ => true).ToList();

Оригинал:

Не блокируйте синхронно асинхронный код. Это плохо сказывается на производительности и может привести к тупикам.

Если вы хотите сохранить синхронность приложения, рекомендуется использовать старый синхронный драйвер.

В новом драйвере v2.0 опция async должна выглядеть следующим образом это:

async Task FooAsync()
{
    var list = await collection.Find(_ => true).ToListAsync();
}

С MongoDb версии 2.2.4 реализация немного изменилась. Следуя рекомендациям, давайте построим соединение MongoDb следующим образом:

public static class PatientDb
{
    public static IMongoCollection<Patient> Open()
    {
        var client = new MongoClient("mongodb://localhost");
        var db = client.GetDatabase("PatientDb");
        return db.GetCollection<Patient>("Patients");
    } 
}

Теперь возвращается интерфейс IMongoCollection вместо экземпляра конкретного класса типа MongoCollection. Больше нет необходимости создавать экземпляр сервера, чтобы получить базу данных, клиент может связаться с базой данных напрямую.

Тогда в контроллере делается так:

public class PatientController : ApiController
{
    private readonly IMongoCollection<Patient> _patients;

    public PatientController()
    {
        _patients = PatientDb.Open();
    }
    public IEnumerable<Patient> Get()
    {
        return _patients.Find(new BsonDocument()).ToEnumerable();
    }
}

Где _patients - это IMongoCollection и to получить всех пациентов вместо того, чтобы использовать FindAll() теперь используется Find(), где фильтр является новым экземпляром BsonDocument.

Это с драйвером MongoDb C# 2.2

Новый драйвер C# является асинхронным. Нравится вам это или нет, но с этим надо разобраться. Он вступит в пригодится в будущем. Но пока.....

В коде ниже асинхронный вызов фактически делается синхронным из-за кода "результат.Помощью getawaiter().Метод getresult();". Это заставляет асинхронный код выполняться до завершения в обычном потоке.

    static void MongoGoNow()
    {
        IMongoCollection<ClassA> collection = db.GetCollection<ClassA>(Collection.MsgContentColName);
        var result = TestFind(collection);
        result.GetAwaiter().GetResult();
        //What's next???
    }

    static async Task TestFind(IMongoCollection<ClassA> MyCollection)
    {
        var filter = new BsonDocument();
        var count = 0;
        using (var cursor = await MyCollection.FindAsync(filter))
        {
            while (await cursor.MoveNextAsync())
            {
                var batch = cursor.Current;
                foreach (var document in batch)
                {
                    // process document
                    count++;
                }
            }
        }       

Можно также объединить последние две строки кода в методе Main следующим образом: образом:

    static void MongoGoNow()
    {
        IMongoCollection<ClassA> collection = db.GetCollection<ClassA>(Collection.MsgContentColName);
        TestFind(collection).GetAwaiter().GetResult();
        //What's next???
    }

Чтобы получить все, вы можете использовать пустой фильтр Согласно документации

FilterDefinition<T>.Empty

Например

    public async Task<IEnumerable<ClassA>> GetAllAsync() =>
                await database.GetCollection<ClassA>(Collection.MsgContentColName)
               .Find(FilterDefinition<ClassA>.Empty).ToListAsync();