在LINQ中的async/await中where子句不起作用 [英] async/await inside LINQ where clause not working

查看:38
本文介绍了在LINQ中的async/await中where子句不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆