重用 IAsyncEnumerable 实例而无需再次迭代
Reuse a IAsyncEnumerable instance without having to iterate again
我目前正在编写这样的方法:
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()
是一种迭代我的数据库的方法,可以被认为是一项昂贵的操作。有什么方法可以像我通常使用 IEnumerable<T>
那样保存我的 IAsyncEnumerable<T>
并在我的代码中重复使用它?
我考虑过使用 ToListAsync()
,但我不确定这是否被认为是好的做法。我还读到我可以 return a Task<IAsyncEnumerable<T>>
并可能用它做点什么。处理这个问题的最佳方法是什么?我想实施最有效的解决方案。
为什么不简单地使用 SingleOrDefaultAsync? Assuming your entity is a reference type you can get your single item, check if it is null to handle the empty-case. Another alternative is always to convert the enumerable to a list。然后,您可以根据需要对其进行多次迭代。
如果返回的单个 UserEntity
有可能是 null
,并且您想区分无实体和 one-null-entity,您可以安装 System.Linq.Async 打包并执行此操作:
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();
}
此查询利用了 ValueTuple<UserEntity, bool>
的默认值为 (null, false)
的事实。
尽管使用 AsAsyncEnumerable
may not be as efficient as using the SingleOrDefaultAsync
方法,因为数据提供者可能会创建优化程度较低的执行计划。
我目前正在编写这样的方法:
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()
是一种迭代我的数据库的方法,可以被认为是一项昂贵的操作。有什么方法可以像我通常使用 IEnumerable<T>
那样保存我的 IAsyncEnumerable<T>
并在我的代码中重复使用它?
我考虑过使用 ToListAsync()
,但我不确定这是否被认为是好的做法。我还读到我可以 return a Task<IAsyncEnumerable<T>>
并可能用它做点什么。处理这个问题的最佳方法是什么?我想实施最有效的解决方案。
为什么不简单地使用 SingleOrDefaultAsync? Assuming your entity is a reference type you can get your single item, check if it is null to handle the empty-case. Another alternative is always to convert the enumerable to a list。然后,您可以根据需要对其进行多次迭代。
如果返回的单个 UserEntity
有可能是 null
,并且您想区分无实体和 one-null-entity,您可以安装 System.Linq.Async 打包并执行此操作:
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();
}
此查询利用了 ValueTuple<UserEntity, bool>
的默认值为 (null, false)
的事实。
尽管使用 AsAsyncEnumerable
may not be as efficient as using the SingleOrDefaultAsync
方法,因为数据提供者可能会创建优化程度较低的执行计划。