问题描述
我目前正在编写这样的方法:
public async Task<usermodel> GetUserByUserIdAsync(string userId)
{
IQueryable<UserEntity> usersQuery = BuildQueryable(userId);
bool any = await usersQuery.ExecuteQuery().AnyAsync();
if (!any) return null; // wanna do other logic in the future
return (await usersQuery.ExecuteQuery().SingleAsync()).Tousermodel();
}
如您所见,我调用了 await usersQuery.ExecuteQuery()
两次,而 ExecuteQuery()
是一种迭代我的数据库的方法,可能被认为是一项开销很大的操作。有什么办法可以像往常一样使用 IAsyncEnumerable<T>
保存我的 IEnumerable<T>
并在整个代码中重复使用它吗?
我考虑过在其上使用 ToListAsync()
,但我不确定这是否被认为是好的做法。我还读到我可以返回一个 Task<IAsyncEnumerable<T>>
并用它做一些事情。处理这个问题的最佳方法是什么?我想实施最有效的解决方案。
解决方法
为什么不简单地使用 SingleOrDefaultAsync?假设您的实体是引用类型,您可以获得单个项目,检查它是否为 null 以处理空情况。另一种选择是始终转换 enumerable to a list。然后,您可以根据需要对其进行多次迭代。
,如果单个返回的 UserEntity
可能是 null
,并且您想区分无实体和一个空实体,您可以安装 {{3}打包并执行此操作:
public async Task<UserModel> GetUserByUserIdAsync(string userId)
{
IQueryable<UserEntity> usersQuery = BuildQueryable(userId);
var (userEntity,exists) = await usersQuery
.AsAsyncEnumerable()
.Select(x => (x,true))
.FirstOrDefaultAsync();
if (!exists) return null; // wanna do other logic in the future
return userEntity.ToUserModel();
}
此查询利用了 System.Linq.Async 的默认值为 (null,false)
的事实。
不过,使用 ValueTuple<UserEntity,bool>
可能不如使用 AsAsyncEnumerable
方法有效,因为数据提供者可能会创建优化程度较低的执行计划。