【问题标题】:Entity Framework Generic Repository Pattern Async Add Method with Save实体框架通用存储库模式异步添加方法和保存
【发布时间】:2021-04-01 18:14:39
【问题描述】:

我有一个名为 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 的含义。当您await 一个任务时,这意味着它不会阻塞当前线程。它只会等待awaited 方法完成并返回到正在执行的线程或线程池中的任何线程(取决于await 的配置方式)。
  • 改进评论;始终检查 await _context.SaveChangesAsync() 的返回值,以便在返回任何值之前知道保存过程是否已完成。

标签: c# asp.net-mvc asp.net-core async-await entity-framework-core


【解决方案1】:

其实你的基础存储库没有错,但不幸的是,我们大多数人都在使用 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()两个同步方法,不仅顺序而且调用者不能得到调用权,也就是不能及时响应,必须等到两个方法都执行完。 我希望这会有所帮助

【讨论】:

  • 所以我想知道这些方法中哪一种在通用存储库模式中更准确?异步任务 AddAsync() { await AddAsync() await SaveAsync() } 或 Add() { Save(); } Save() { } AddAsync() { Add();等待 SaveAsync(); } 哪一个是最佳实践?
【解决方案2】:
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();
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多