【问题标题】:Creating an Async version of a Generic Repository创建通用存储库的异步版本
【发布时间】:2014-10-01 17:50:00
【问题描述】:

我有一个实现以下接口的通用存储库:

public interface IRepository
{
  IUnitOfWork UnitOfWork { get; }


  IEnumerable<TEntity> GetWithRawSql<TEntity>(string query, params object[] parameters) where TEntity : class;

  TEntity GetByKey<TEntity>(object keyValue) where TEntity : class;

  IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class;

  IQueryable<TEntity> GetQuery<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;

  IQueryable<TEntity> GetQuery<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  TEntity Single<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;

  TEntity Single<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  TEntity First<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;

  TEntity First<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  void Add<TEntity>(TEntity entity) where TEntity : class;

  void Attach<TEntity>(TEntity entity) where TEntity : class;

  void Delete<TEntity>(TEntity entity) where TEntity : class;

  void Delete<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;

  void Delete<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  void Update<TEntity>(TEntity entity) where TEntity : class;

  IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  IEnumerable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;

  TEntity FindOne<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;

  TEntity FindOne<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;

  IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class;

  IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex,
    int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class;

  IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> criteria,
    Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize,
    SortOrder sortOrder = SortOrder.Ascending) where TEntity : class;

  IEnumerable<TEntity> Get<TEntity, TOrderBy>(ISpecification<TEntity> specification,
    Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize,
    SortOrder sortOrder = SortOrder.Ascending) where TEntity : class;

  int Count<TEntity>() where TEntity : class;

  int Count<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;

  int Count<TEntity>(ISpecification<TEntity> criteria) where TEntity : class;
}

此接口属于 huyrua's blog 实现的通用存储库的修改版本。 我需要一些方法的异步版本。例如,我有以下 GetWithRawSql 方法的实现:

public IEnumerable<TEntity> GetWithRawSql<TEntity>(string query, params object[] parameters) where TEntity : class
{
    return DbContext.Set<TEntity>().SqlQuery(query, parameters).ToList();
}

对于异步版本,我实现了以下内容:

public async Task<IEnumerable<TEntity>> GetWithRawSqlAsync<TEntity>(string query, params object[] parameters) where TEntity : class
{
    return await Task.Run(() => GetWithRawSql<TEntity>(query, parameters));
}

GetByKey 方法也一样:

public async Task<TEntity> GetByKeyAsync<TEntity>(object keyValue) where TEntity : class
{
    return await Task.Run(() => GetByKey<TEntity>(keyValue));
}

上面的实现看起来像是一个快速而肮脏的工作。您将如何实现上述方法以及使用时可能会遇到什么问题

await Task.Run(() => GetWithRawSql<TEntity>(query, parameters));

在我的存储库中?对于完整的植入,您可以查看博客并为您提供信息,我使用实体框架 6.1.1。

【问题讨论】:

  • EF6 已经是async,只需委派您的电话。
  • 您能详细说明一下吗?
  • 阅读我链接到的文章...

标签: c# .net entity-framework generics async-await


【解决方案1】:

你正在做的是async over sync,它在处理异步工作时是一种反模式。

EF6 已经带有一个开箱即用的异步 API,它不使用任何幕后的新线程,而是使用数据库公开的异步 IO 工作来消耗其工作。

当您使用异步而不是同步时,您通常最终会启动一堆线程,这些线程基本上坐在那里等待查询返回,并且根本不能很好地扩展,并且使用不是真的冗余线程在处理 IO 绑定操作时需要。此外,当人们看到async 方法时,他们从不说“他可能正在使用一个新线程来运行同步版本”,他们通常说“这个async 实现将节省我不必要的线程用于 IO 绑定工作"

这是一个使用 EF6 完成的简单 UpdateAsync 方法:

public static async Task<string> UpdateAsync(Customer obj)
{
    NorthwindEntities db = new NorthwindEntities();

    // This is an async method
    Customer existing = await db.Customers.FindAsync(obj.CustomerID);         
    existing.CompanyName = obj.CompanyName;
    existing.ContactName = obj.ContactName;
    existing.Country = obj.Country;

    await db.SaveChangesAsync(); // This is an async method

    return "Customer updated successfully!";
}

您可以阅读有关 EF6 和异步方法的更多信息:

  1. Performing Asynchronous Operations Using Entity Framework
  2. Async Query & Save (EF6 onwards)

【讨论】:

    猜你喜欢
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 2017-04-10
    相关资源
    最近更新 更多