在获取集合时,是否可以将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);
这方面有什么好的做法?
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中查询数据库。