在LINQ中的async/await中where子句不起作用 [英] async/await inside LINQ where clause not working
问题描述
我正试图在LINQ语句中使数据库查询异步,但是我遇到了一个错误.下面的代码在没有async/await的情况下运行正常
I'm tring to make a database query inside a LINQ statement asynchronous, but I'm running into an error. The code below runs fine with out async/await
var newEntities = _repositoryMapping.Mapper.Map<List<Entry>>(entries);
newEntities = newEntities.Where(async e => await !_context.Entries.AnyAsync(c => c.Id == e.Id)).ToList();
严重性代码描述项目文件行抑制状态错误CS4010无法将异步Lambda表达式转换为委托类型"Func< Entry,bool>".异步lambda表达式可能会返回无效,任务或任务,都不能转换为'Func< Entry,bool>'
Severity Code Description Project File Line Suppression State Error CS4010 Cannot convert async lambda expression to delegate type 'Func<Entry, bool>'. An async lambda expression may return void, Task or Task, none of which are convertible to 'Func<Entry, bool>'
除了将其分解为foreach循环外,如何使它与async/await一起使用?
Other than breaking this up into a foreach loop, how can I make this work with async/await?
推荐答案
如果您关心性能,则代码应该更聪明.您只需要发送一个查询并检查数据库中已经存在的内容即可.
If you care about performance, code should be smarter. You just need to send one query and check what is already present in database.
准备好的扩展名,可以通过通用方式做到这一点:
Prepared extension which can do that in generic way:
newEntities = (await newEntities.FilterExistentAsync(_context.Entries, e => e.Id)).ToList();
实施不是那么复杂
public static class QueryableExtensions
{
public static async Task<IEnumerable<T>> FilterExistentAsync<T, TProp>(this ICollection<T> items,
IQueryable<T> dbQuery, Expression<Func<T, TProp>> prop, CancellationToken cancellationToken = default)
{
var propGetter = prop.Compile();
var ids = items.Select(propGetter).ToList();
var parameter = prop.Parameters[0];
var predicate = Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(TProp) }, Expression.Constant(ids), prop.Body);
var predicateLambda = Expression.Lambda(predicate, parameter);
var filtered = Expression.Call(typeof(Queryable), "Where", new[] {typeof(T)}, dbQuery.Expression,
predicateLambda);
var selectExpr = Expression.Call(typeof(Queryable), "Select", new[] {typeof(T), typeof(TProp)}, filtered, prop);
var selectQuery = dbQuery.Provider.CreateQuery<TProp>(selectExpr);
var existingIds = await selectQuery.ToListAsync(cancellationToken);
return items.Where(i => !existingIds.Contains(propGetter(i)));
}
}
这篇关于在LINQ中的async/await中where子句不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!