从IDbAsyncQueryProvider投影

时间:2015-03-09 18:17:55

标签: entity-framework async-await automapper

我有一个项目,我们将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:源IQueryable的提供程序未实现IDbAsyncQueryProvider。只有实现IDbAsyncQueryProvider的提供程序才能用于Entity Framework异步操作。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=287068

这是Automapper对[还]不支持的东西,还是我缺少另一种方法或扩展?

1 个答案:

答案 0 :(得分:2)

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

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>();