1

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

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()它,但我不确定这是否被认为是好的做法。我还读到我可以返回 aTask<IAsyncEnumerable<T>>并用它做点什么。处理这个问题的最佳方法是什么?我想实施最有效的解决方案。

4

2 回答 2

4

为什么不简单地使用SingleOrDefaultAsync?假设您的实体是一个引用类型,您可以获得您的单个项目,检查它是否为 null 以处理空案例。另一种选择是始终将enumerable 转换为 list。然后,您可以随意迭代它多次。

于 2021-06-02T12:57:24.027 回答
1

如果返回的单个可能UserEntitynull,并且您想区分无实体和单空实体,则可以安装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>该查询利用了 a 的默认值为的事实(null, false)

但是,使用AsAsyncEnumerable可能不如使用该SingleOrDefaultAsync方法有效,因为数据提供者可能会创建一个优化程度较低的执行计划。

于 2021-06-02T18:52:29.523 回答