从 IDbAsyncQueryProvider 投影

Projecting from an IDbAsyncQueryProvider

我有一个项目,在这个项目中我们使用 Automapper Project() 实体从我们的数据访问层进入我们的域 类,这些实体被外部调用者(即 WebAPI、windows 服务等)。这个想法是我们想从实际的数据库实现中抽象出我们的域模型,但是域模型通常由 至少 数据库中的成员组成,因此 Automapper 构建这些域使用它的投影功能更容易建模。

这导致代码类似于:

public class DbTask
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Task
{
   public int Id { get; set; }
   public string Name { get; set; }
   public User Assignee { get; set; }
   public Priority CurrentPriority { get; set; }
}

然后是如下所示的业务服务实现:

public IQueryable<Task> QueryTasksByUser(int userId)
{
   return dbContext
            .Where(x => x.Assignee.Id == userId)
            .Project()
            .To<Task>();
}

那么在 API 层我们想尽可能地利用 async/await,所以我想知道 Automapper 是否对此有任何支持。如果我这样写我的方法:

public async Task<IHttpActionResult> GetTopTaskForCurrentUser()
{
   var task = await _taskService
        .GetTasksByUser(Thread.CurrentPrincipal.AsUser().UserId)
        .Where(x => x.CurrentPriority == Priority.Top)
        .SingleOrDefaultAsync();

   return Ok(task);
}

我得到以下异常:

System.InvalidOperationException : The provider for the source IQueryable doesn't implement IDbAsyncQueryProvider. Only providers that implement IDbAsyncQueryProvider can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068.

这是 Automapper [还]不支持的东西,还是我缺少其他方法或扩展?

您只需确保以正确的顺序调用这些方法:

return await dbContext.Users
     .Where(user => user.Id == id)
     .Project().To<UserDto>()
     .ToListAsync();

将 Project.To 放在与 "Select" 相同的位置,它工作正常。

我通常创建一个扩展方法来包装投影和异步:

public static async Task<List<TDestination>>
    ToListAsync<TDestination>(
    this IProjectionExpression projectionExpression)
{
    return await projectionExpression.To<TDestination>().ToListAsync();
}

return await dbContext.Users
    .Where(u => u.Id == id)
    .Project().ToListAsync<UserDto>();