我使用带有c#和异步方法的MongoDB在标准存储库类中创建了一些方法,并且我偶然发现了一些奇怪的行为。
最后它可能并不奇怪,而问题在于我自己对异步编程缺乏经验。
考虑以下代码:
public async Task<T> GetItem<T>(ObjectId id) where T : BaseItemEntity
{
var col = GetTypedCollection<T>();
var model = await col.FindAsync(x => x.Id == id);
return await model.FirstOrDefaultAsync();
}
现在完全没问题,没有编译错误,但实际上我不确定它的正确呼叫等待2次。
现在考虑以下代码:
public async Task<T> GetItem<T>(ObjectId id) where T : BaseItemEntity
{
var col = GetTypedCollection<T>();
var model = await col.FindAsync(x => x.Id == id).FirstOrDefaultAsync();
return model;
}
根据编译器,这是非法的。它抱怨FirstOrDefaultAsync()不是一种可用的调用方法。我必须首先调用.Result来访问.FirstOrDefaultAsync()。
这里发生了什么?
答案 0 :(得分:3)
var model = await col.FindAsync(x => x.Id == id).FirstOrDefaultAsync();
应该是:
var model = await (await col.FindAsync(x => x.Id == id)).FirstOrDefaultAsync();
这是因为FindAsync返回一个Task对象,FirstOrDefaultAsync不适用于该对象。等待操作产生实际结果。
这是async / await IMO最烦人的事情之一,因为它需要括号或变量来保存等待结果以便进一步处理。
答案 1 :(得分:1)
我认为它实际应该是
var model = await (await col.FindAsync(x => x.Id == id)).FirstOrDefaultAsync();
两个Async方法都返回一个Task对象,而Tasks没有FirstOrDefault()方法(这就是为什么需要await in())。另一个是需要的,因为这种方式模型是你的对象而不是任务。