我有一个项目,我们将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对[还]不支持的东西,还是我缺少另一种方法或扩展?
答案 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>();