了解 MongoDB 新 C# 驱动程序的变化(异步和等待)

Understanding the changes in MongoDB new C# driver (Async and Await)

新的 C# 驱动程序完全是异步的,在我的理解中有点扭曲了旧的设计模式,例如 n 层架构中的 DAL。

在我的 Mongo DAL 中,我曾经做过:

public T Insert(T entity){
     _collection.Insert(entity);
     return entity;
}

这样我可以得到持久化的ObjectId

今天,一切都是异步的,例如 InsertOneAsync
InsertOneAsync 完成时,Insert 方法现在如何 return entity?你能举个例子吗?

了解 async / await 的基础知识很有帮助,因为它是一个有点漏洞的抽象并且有很多陷阱。

基本上,您有两个选择:

  • 保持同步。在这种情况下,在异步调用中分别使用 .Result.Wait() 是安全的,例如像

    // Insert:
    collection.InsertOneAsync(user).Wait();
    
    // FindAll:
    var first = collection.Find(p => true).ToListAsync().Result.FirstOrDefault();
    
  • 在您的代码库中实现异步。不幸的是,异步操作相当 'infectious',所以要么将几乎所有内容都转换为异步,要么不转换。小心,mixing sync and async incorrectly will lead to deadlocks。使用异步有很多优点,因为您的代码可以在 MongoDB 仍在工作时继续 运行,例如

    // FindAll:
    var task = collection.Find(p => true).ToListAsync();
    // ...do something else that takes time, be it CPU or I/O bound
    // in parallel to the running request. If there's nothing else to 
    // do, you just freed up a thread that can be used to serve another 
    // customer...
    // once you need the results from mongo:
    var list = await task;
    

就我而言:当我收到此错误时:

The source IQueryable doesn't implement IAsyncEnumerable. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.

我已经为 mongodb 实现了异步 where 函数,如下所示。

public async Task<IEnumerable<TEntity>> Where(Expression<Func<TEntity, bool>> expression = null)
{
     return await context.GetCollection<TEntity>(typeof(TEntity).Name, expression).Result.ToListAsync();
}