在获取集合时,是否可以将lambda/linq与wait一起使用

本文关键字:linq wait 一起 lambda 集合 获取 是否 | 更新日期: 2023-09-27 17:59:18

我最近使用了很多Async,因为客户端应用程序是一个移动应用程序,使用非ui阻塞api很重要。

我一直在做这样的查询:

var answer = _baseCommands.GetAll<Answer>().FirstOrDefault(x => x.QuestionId == question1.QuestionId && x.IsCorrect);

这是一种方法,但我也使用这种方法:

 IQueryable<T> GetAll<T>() where T : class;
 Task<IQueryable<T>> GetAllAsync<T>() where T : class;

这是在BaseCommands:中实现的

public IQueryable<T> GetAll<T>()
            where T : class
        {
            return _askDatabase.Set<T>();
        }
        public async Task<IQueryable<T>> GetAllAsync<T>()
            where T : class
        {
            return await Task.FromResult(_askDatabase.Set<T>());
        }

有没有写这样的代码,这样我就可以得到所有的aysnc,但有一个lambda:

 var answer = await _baseCommands.GetAllAsync<Answer>().Result.FirstOrDefault(x => x.QuestionId == question1.QuestionId && x.IsCorrect);

这方面有什么好的做法?

在获取集合时,是否可以将lambda/linq与wait一起使用

老实说,异步创建IQueryable<T>没有多大意义。创建的对象只是表示问题,它本身并没有执行查询,所以它可能非常便宜;记住LINQ是懒惰的;查询将在枚举时执行,而不是在枚举之前执行。

如果您返回一个枚举查询,例如调用ToList(),异步方法会更有意义。如果连接有很高的延迟,并且从数据库带回的数据量不是很大,那么这可能是有意义的。

是的,可以用():包装

(await _baseCommands.GetAllAsync<Answer>())
                .FirstOrDefault(x => x.QuestionId == question1.QuestionId && x.IsCorrect);

说明:

await _baseCommands.GetAllAsync<Answer>().FirstOrDefault没有编译,因为Task没有该方法的定义。但是,如果将等待调用封装在()中,那么就可以对该任务的结果执行.FirstOrDefault。注意,这执行过滤synchronously

代码附带说明:

在API中使用Task.FromResult是无用的,您在这里不是异步地执行任务。这主要用于实体模型。您需要使用Task.Run()来异步执行查询。此外,您最好执行查询并使用.ToList()返回Collection,以便在后台线程中执行查询。

如果您可以更改获取数据的API,我建议您添加一些重载:

Task<List<T>> GetAllAsync<T>(Expression<Func<T, bool>> predicate) where T : class;

然后可以使用该谓词直接在API中查询数据库。