实体框架通用存储库模式异步添加方法与保存

问题描述

我有一个名为 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 programmingAsync,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();
            }
        }