无需再次迭代即可重用 IAsyncEnumerable 实例

问题描述

我目前正在编写这样的方法

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 方法有效,因为数据提供者可能会创建优化程度较低的执行计划。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...