c# - 创建通用存储库的异步版本

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

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

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;
}

此接口(interface)属于由 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));

在我的仓库中?对于完整的植入,您可以查看博客,为了您的信息,我使用 Entity Framework 6.1.1。

最佳答案

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

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

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

这是一个使用 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)

关于c# - 创建通用存储库的异步版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25200273/

相关文章:

c# - 安装的 Dotnet 工具在 Ubuntu WSL2 上给出错误 "Could not execute because the specified command or file was not found."

c# - 从不同窗口的构造函数更新 UI 不起作用

c# - 如果时区规则更改,以前保存的日期时间的 UTC 到本地时间转换

c# - asp.Net 如何将数据保存到 Controller 中的联结表

c# - 如何在控制台应用程序中添加 App.Config 文件

c# - 注册动态类型的简单注入(inject)器

c# - AutoMapper 在 IQueryable 上调用 ProjectTo<T>() 时抛出 StackOverflowException

c# - 当前服务的名称,以防同一个 exe 被设置为多个服务

c# - 变量在声明后似乎正在改变类型

.net - 使用 concat() 从 mysql 存储过程检索并绑定(bind)到 datagridview 时出错