新的C#驱动程序完全是异步的,在我的理解中,它有点扭曲了旧的设计模式,例如n层体系结构中的DAL。
在我以前使用的Mongo DAL中:
public T Insert(T entity){
_collection.Insert(entity);
return entity;
}
通过这种方式,我可以获得持久的ObjectId
。
[今天,一切都是异步的,例如InsertOneAsync
。Insert
完成后,entity
方法现在将如何返回InsertOneAsync
?你能举个例子吗?
了解async
/ await
的基本知识很有帮助,因为它是一个有点泄漏的抽象,并且有很多陷阱。
基本上,您有两个选择:
保持同步。在这种情况下,可以安全地在异步调用中分别使用.Result
和.Wait()
,例如像
// Insert:
collection.InsertOneAsync(user).Wait();
// FindAll:
var first = collection.Find(p => true).ToListAsync().Result.FirstOrDefault();
在您的代码库中进行异步处理。不幸的是,异步执行是非常“传染性的”,因此您可以将几乎所有内容都转换为异步。小心,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;
就我而言:当我遇到此错误时:
源IQueryable未实现IAsyncEnumerable。仅来源实现IAsyncEnumerable可用于实体框架异步操作。
我已经为mongodb实现了async where函数,如下。
public async Task<IEnumerable<TEntity>> Where(Expression<Func<TEntity, bool>> expression = null)
{
return await context.GetCollection<TEntity>(typeof(TEntity).Name, expression).Result.ToListAsync();
}