问题描述
我有一个名为 Repository 的基本存储库类。谁能解释一下我应该如何使此类中的方法异步?
public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : Entity
{
private readonly DbContext _context;
private readonly DbSet<TEntity> _dbSet;
public Repository(DbContext context)
{
_context = context;
_dbSet = context.Set<TEntity>();
}
public TEntity Add(TEntity entity)
{
entity.CreateDate = DateTime.Now;
_dbSet.Add(entity);
Save();
return entity;
}
public void Save()
{
_context.SaveChanges();
}
}
我尝试使其异步,但我无法决定添加和保存方法如何同时异步。我的实验在这里,它看起来不对,因为它包含两个等待。
public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : Entity
{
private readonly DbContext _context;
private readonly DbSet<TEntity> _dbSet;
public Repository(DbContext context)
{
_context = context;
_dbSet = context.Set<TEntity>();
}
public async Task<TEntity> AddAsync(TEntity entity)
{
entity.CreateDate = DateTime.Now;
await _dbSet.AddAsync(entity);
await SaveAsync();
return entity;
}
public async Task SaveAsync()
{
await _context.SaveChangesAsync();
}
}
解决方法
其实你的基础仓库并没有错,但不幸的是,我们大多数人都在使用
Asynchronous programming
和 Async,await
方式没有深刻理解。
无论如何,我建议访问此链接 Asynchronous Programming
1. await 运算符应用于异步方法中的任务,并在方法的执行中插入一个挂起的起点,直到等待任务完成。 任务指示正在进行的工作。
2、await 只能用在 async 关键字修饰的异步方法中。 这种使用 async 修饰符定义并且通常包含一个或多个 await 表达式的方法称为异步方法。
3,await的唯一目的就是在调用异步方法XXAsync()时挂起这个方法。它认为这个方法是一个耗时的方法,主线程,或者调用这个方法的线程。不要以这种方式等待。 并同时标记。当前正在执行的线程运行完毕后,会从这里恢复运行,所以await标签的异步方法下面的代码或方法不会运行。您必须等待此方法。执行!
4,加不加await,方法是异步还是同步无所谓 下面写一个例子
private static async Task XAsync()
{
await XXAsync();
OtherMothod();
}
5。当运行到 await XXAsync() 时,对方法 XAsync() 的调用将不再运行并直接返回,就像我们程序代码中的 return 语句一样。这样做的好处是调用线程不会等待这个耗时的线程。直接让调用线程跑下来,
6。如果调用线程一直有await链向上,就像set方法中的return一样,会一层一层的向上返回,返回到主线程,每个“子线程”等待耗时的I/O处理,例如操作数据库和网络流
7。我们希望以多线程或多任务的方式执行我们的程序,让耗时的任务得到执行,同时给调用者一个快速的响应,不管他是否完成了任务!这才是真正的目的。
private static async TaskXAsync()
{
await XXAsync();
await XXXAsync();
}
XXXAsync() 必须等待 XXAsync() 方法执行!这不会影响调用者的响应速度,但是会影响我们代码的执行效率,与两种同步方式略有不同。
private static async TaskXAsync()
{
XX();
XXX();
}
像上面例子中的XX()和XXX()两种同步方法,不仅顺序不对而且调用者无法得到调用正确,也就是不能及时响应,必须等到两个方法都执行完毕。 我希望这会有所帮助
,public interface IRepository<TEntity> where TEntity : class
{
IQueryable<TEntity> GetAll();
IQueryable<TEntity> GetByWhere(Expression<Func<TEntity,bool>> predicate);
Task CreateAsync(TEntity entity);
Task UpdateAsync(TEntity entity);
Task DeleteAsync(TEntity entity);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly DbContext dbContext;
public Repository(DbContext dbContext)
{
this.dbContext = dbContext;
}
public async Task CreateAsync(TEntity entity)
{
await dbContext.Set<TEntity>().AddAsync(entity);
await dbContext.SaveChangesAsync();
}
public async Task DeleteAsync(TEntity entity)
{
dbContext.Set<TEntity>().Remove(entity);
await dbContext.SaveChangesAsync();
}
public IQueryable<TEntity> GetAll()
{
return dbContext.Set<TEntity>().AsNoTracking();
}
public IQueryable<TEntity> GetByWhere(System.Linq.Expressions.Expression<Func<TEntity,bool>> predicate)
{
return dbContext.Set<TEntity>().Where(predicate).AsNoTracking();
}
public async Task UpdateAsync(TEntity entity)
{
dbContext.Update(entity);
await dbContext.SaveChangesAsync();
}
}