何时在通用库中使用异步?

When to use async in generic libraries?

我最近在寻找通用存储库模式的好例子,但被一个完全不同的主题搞糊涂了。 Asyncawait。这是简化界面:

public interface IGenericRepository<TEntity> where TEntity : class
{ 
    Task<TEntity> GetById(int id);
}

这是该接口的两个实现示例:

A:

public async Task<TEntity> GetById(int id)
{
    return await _dbContext.Set<TEntity>()
                .AsNoTracking()
                .FirstOrDefaultAsync(e => e.Id == id);
}

B:

public Task<T> GetById(int id) => Context.Set<T>().FindAsync(id);

在这两种情况下,它都是来自通用 RepositoryBase class 的方法,它将被真正的 Repository classes 继承。在一种情况下使用 async await,在第二种情况下使用 而不是 。为什么?

并跟进问题:如果有区别,我们什么时候应该使用 async await,什么时候应该只 return 而 Task

I was recently looking for nice example of generic repository pattern

通用存储库模式通常被认为是一种反模式,正是因为它太通用了。就个人而言,我更喜欢数据层抽象的端口和适配器样式,它让应用程序定义它需要的 DAL 方法。尽管在许多情况下,直接 EF 工作正常(这似乎是迄今为止最常见的选择)。

In one case async await is used, in the second case not. Why?

关于何时 elide async/await 有一些注意事项。它主要归结为异常处理。返回任务的方法应该在这些任务上放置异常,而不是直接引发异常;那是具有异步签名的方法的隐式契约。

因此,如果 ContextSet<T> 抛出:

,此代码将(错误地)直接抛出
public Task<T> GetById(int id) => Context.Set<T>().FindAsync(id);

一般来说,保持async/await是安全的选择;省略它们是一个小的性能优化,应该只在 considering the pitfalls.

之后完成