从 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>();
我有一个项目,在这个项目中我们使用 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>();