异步方法中的 LINQ 查询问题:“无法翻译 LINQ 表达式”

问题描述 投票:0回答:1

我有一个 C# 异步方法,用于检索具有各种嵌套包含和过滤器的用户列表。当我不传递 arbsResponse 参数时该方法工作正常,但当我传递时遇到异常。

方法如下:

`

        public  async Task<List<User>> GetActiveNonDeletedUsersWithValidBookmakersAndFilters(List<ArbsResponse> arbsResponse, List<ValuebetArbsResponse> valuebetResponses)
        {
            var users = await _context.Users
                .Where(u => u.TaskIsActive && !u.Deleted)
                .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
                    .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                        .ThenInclude(uf => uf.UsersFilterCountries.Where(ufc => !ufc.Deleted))
                .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
                    .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                        .ThenInclude(uf => uf.UsersFilterLeagues.Where(ufl => !ufl.Deleted))
                .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
                    .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                        .ThenInclude(uf => uf.UsersFilterStrategyTypes.Where(ufst => !ufst.Deleted))
                .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
                    .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                        .ThenInclude(uf => uf.UsersFilterBetTypes.Where(ufb => !ufb.Deleted))
                .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
                    .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                        .ThenInclude(uf => uf.UsersFilterBetTimings.Where(ufbt => !ufbt.Deleted))
                    .Where(u => u.UsersBookmakers.Any(ub => ub.UsersFilters.Any(uf => uf.IsActive && !uf.Deleted &&
            (
                arbsResponse.Any(arb =>
                    (arb.MinKoef >= uf.MinimalKoef && arb.MaxKoef <= uf.MaximalKoef) 
                ) ||
                valuebetResponses.Any(valuebet =>
                    (valuebet.MinKoef >= uf.MinimalKoef && valuebet.MaxKoef <= uf.MaximalKoef) 
                ))
            ))).ToListAsync();

    return users;
}

`

当我使用 arbsResponse 参数调用此方法时,出现以下异常:

`

System.InvalidOperationException: 'The LINQ expression 'arb => arb.MinKoef >= EntityShaperExpression: 
    Core.Entities.UsersFilter
    ValueBufferExpression: 
        ProjectionBindingExpression: Inner
    IsNullable: False
.MinimalKoef && arb.MaxKoef <= EntityShaperExpression: 
    Core.Entities.UsersFilter
    ValueBufferExpression: 
        ProjectionBindingExpression: Inner
    IsNullable: False
.MaximalKoef' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'

`

LINQ 查询似乎无法转换为 Entity Framework Core 可以在数据库端执行的形式。

当我不传递 arbsResponse 参数时,该方法执行时没有任何问题。谁能帮助我理解为什么会发生这个异常以及如何修改查询以便它可以正确翻译和执行?

附加信息 实体框架核心版本:6.0.32 .NET版本:6.0 任何意见或建议将不胜感激。谢谢!

我尝试从查询中删除 arbsResponse 参数,并且该方法的执行没有任何问题。这让我相信问题出在涉及 arbsResponse 的查询部分。我还尝试通过减少嵌套的 Include 和 ThenInclude 子句的数量来简化查询,但当 arbsResponse 是查询的一部分时,错误仍然存在。

我希望查询执行并返回具有活动的、未删除的任务并满足基于 arbsResponse 和 valuebetResponses 的指定过滤条件的用户列表。

sql-server async-await entity-framework-core linq-to-sql c#-6.0
1个回答
0
投票

EF Core 无法将某些 LINQ 表达式转换为 SQL,尤其是在涉及复杂的嵌套查询和方法调用时。

在这种情况下,我认为

.Where(u => u.UsersBookmakers.Any(ub => ....
可能应该单独执行,更像是分解查询。

你可以尝试这样的分割(依靠客户端进行第二次过滤):

public async Task<List<User>> GetActiveNonDeletedUsersWithValidBookmakersAndFilters(List<ArbsResponse> arbsResponse, List<ValuebetArbsResponse> valuebetResponses)
{
    var users = await _context.Users
        .Where(u => u.TaskIsActive && !u.Deleted)
        .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
            .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                .ThenInclude(uf => uf.UsersFilterCountries.Where(ufc => !ufc.Deleted))
        .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
            .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                .ThenInclude(uf => uf.UsersFilterLeagues.Where(ufl => !ufl.Deleted))
        .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
            .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                .ThenInclude(uf => uf.UsersFilterStrategyTypes.Where(ufst => !ufst.Deleted))
        .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
            .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                .ThenInclude(uf => uf.UsersFilterBetTypes.Where(ufb => !ufb.Deleted))
        .Include(u => u.UsersBookmakers.Where(ub => !ub.Deleted))
            .ThenInclude(ub => ub.UsersFilters.Where(uf => uf.IsActive && !uf.Deleted))
                .ThenInclude(uf => uf.UsersFilterBetTimings.Where(ufbt => !ufbt.Deleted))
        .ToListAsync();

    var filteredUsers = users.Where(u =>
        u.UsersBookmakers.Any(ub => ub.UsersFilters.Any(uf => uf.IsActive && !uf.Deleted &&
            (
                arbsResponse.Any(arb =>
                    (arb.MinKoef >= uf.MinimalKoef && arb.MaxKoef <= uf.MaximalKoef)
                ) ||
                valuebetResponses.Any(valuebet =>
                    (valuebet.MinKoef >= uf.MinimalKoef && valuebet.MaxKoef <= uf.MaximalKoef)
                )
            )
        ))
    ).ToList();

    return filteredUsers;
}

首先尝试这是否首先解决问题,但请记住,如果数据集很大,将其加载到内存中以供第二个过滤器可能会对性能产生一些影响。

© www.soinside.com 2019 - 2024. All rights reserved.