如何使用async一直到顶部

时间:2017-05-03 18:40:33

标签: c# asynchronous async-await

我有通用存储库,其中包含异步方法FindAsync

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private dynamic _context;
    private DbSet<TEntity> _dbSet;

    protected DbContext Context
    {
        get
        {
            if (_context == null)
            {
                _context = DataContextFactory.GetDataContext();
            }

            return _context;
        }
    }

    protected DbSet<TEntity> DBSet
    {
        get
        {
            if (_dbSet == null)
            {
                _dbSet = Context.Set<TEntity>();
            }

            return _dbSet;
        }
    }

    public virtual IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
    {
        IQueryable<TEntity> qry = DBSet;

        if (predicate != null)
        {
            qry = qry.Where(predicate);
        }

        if (orderExpression != null)
        {
            return orderExpression(qry);
        }

        return qry;
    }

    public virtual IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderExpression = null) where T : class
    {
        DbSet<T> dbSet = Context.Set<T>();
        IQueryable<T> qry = dbSet;

        if (predicate != null)
        {
            qry = qry.Where(predicate);
        }

        if (orderExpression != null)
        {
            return orderExpression(qry);
        }

        return qry;
    }

    public virtual async Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
    {
        return await GetQuery(predicate, orderExpression).ToListAsync();
    }

    public virtual async Task<IEnumerable<T>> FindAsync<T>(Expression<Func<T, bool>> predicate, Func<IQueryable<T>, IOrderedQueryable<T>> orderExpression = null) where T : class
    {
        return await GetQuery<T>(predicate, orderExpression).ToListAsync();
    }
}

然后我创建了一个CustomerRepository,它从通用仓库调用FindAsync

public class CustomerRepository
{
    private readonly IRepository<Customer> _repo;

    /// <summary>
    /// Hookup dependencies
    /// </summary>
    /// <param name="repo"></param>
    public CustomerRepository(IRepository<Customer> repo)
    {
        _repo = repo;

        //Disable entity proxy creation and  lazy loading.
        _repo.LazyLoadingEnabled(false);
    }

    /// <summary>
    /// Gets customer by id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<Customer> GetByIdAsync(Guid id)
    {
        return await _repo.FindAsync(p => p.Id == id).Result.SingleOrDefaultAsync();
    }
}

我遇到的问题是当我致电await _repo.FindAsync(p => p.Id == id).Result.SingleOrDefaultAsync();

它说

  

IEnumerable Customer不包含SingleOrDefaultAsync的定义。

任何人都知道我错过了什么?

3 个答案:

答案 0 :(得分:4)

我认为对await的使用方式存在误解。

await方法上使用async运算符,返回Task类型以暂停执行方法,直到等待的任务完成。

然后将返回值赋给变量。

public async Task<Customer> GetByIdAsync(Guid id)
{
    // Call the async method to get the task returning the customers
    Task<IEnumerable<Customer>> customersTask = _repo.FindAsync(p => p.Id == id);

    // Wait for the customers to be fetched
    IEnumerable<Customer> customers = await customersTask;

    // Get the customer
    return customers.SingleOrDefault();
}

这类似于:

public async Task<Customer> GetByIdAsync(Guid id)
{
    var customers = await _repo.FindAsync(p => p.Id == id);
    return customers.SingleOrDefault();
}

答案 1 :(得分:2)

这是你的一个问题。另一个是你将阻止通话.Resultasync/await通话混合在一​​起。

/// <summary>
/// Gets customer by id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<Customer> GetByIdAsync(Guid id) {
    var records = await _repo.FindAsync(p => p.Id == id);
    return records.AsQueryable().SingleOrDefaultAsync();
}

另外,请确保您有正确的参考QueryableExtensions.SingleOrDefaultAsync Method (IQueryable)

答案 2 :(得分:1)

添加      使用System.Data.Entity  到CustomerRepository.cs

顶部的using语句

更改FindAsync的返回类型以返回IQueryable

请参阅QueryableExtensions vor进一步指导

此外,请不要将阻止调用(.Result)与async / await混合使用,如后面的评论所示。