You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Entity Framework Core中动态合并可变数量查询并单次执行的实现方法

Entity Framework Core中动态合并可变数量查询并单次执行的实现方法

我来帮你搞定这个问题!你当前的代码核心问题出在合并查询的逻辑错误上:Concat是无状态的扩展方法,它不会修改原有的查询对象,而是返回一个全新的合并后查询,但你根本没接收这个返回值;而且你把lastQuery重新赋值为当前selectQuery的操作,直接把之前的合并结果都丢弃了,最后自然只得到第一个查询的结果。

要实现动态合并任意数量的查询,并且单次数据库往返执行,我们只需要修正合并逻辑,让每次合并后的查询都被正确保留即可。下面是修复后的完整代码,我会顺便帮你优化一些细节:

public List<Valuation> GetValuations(List<GetValuationCriteria> valuationCriteriaList)
{
    // 先处理空列表的边界情况,避免空引用异常
    if (!valuationCriteriaList.Any())
    {
        return new List<Valuation>();
    }

    IQueryable<Valuation> combinedQuery = null;

    foreach (var criteria in valuationCriteriaList)
    {
        // 构建当前条件对应的查询
        var selectQuery = DbContext.Valuations
            .Where(w => w.ActivityDate == criteria.ActivityDate 
                && w.ValuationSourceId == criteria.ValuationSourceId 
                && w.ActivityTypeId == criteria.ActivityTypeId 
                && w.CurrencyId == criteria.CurrencyId 
                && w.OrganizationHierarchyId == criteria.OrganizationHierarchyId 
                && w.StatusCode == "A");

        if (combinedQuery == null)
        {
            // 第一个查询直接作为初始合并查询
            combinedQuery = selectQuery;
        }
        else
        {
            // 关键:将当前查询与已合并的查询拼接,并重写赋值给combinedQuery
            // 这里根据需求二选一:
            // 1. Concat = SQL的UNION ALL,直接拼接所有结果(包含重复项,性能更高)
            combinedQuery = combinedQuery.Concat(selectQuery);
            // 2. Union = SQL的UNION,自动去重结果(需要额外的去重逻辑,性能稍低)
            // combinedQuery = combinedQuery.Union(selectQuery);
        }
    }

    // 此时combinedQuery是一个完整的查询树,EF Core会将其翻译成单次SQL请求
    return combinedQuery.ToList();
}

关键细节解释:

  • 必须接收合并后的查询对象:EF Core的Concat/Union方法不会修改原查询,只会返回新的合并查询,所以必须把这个返回值重新赋值给combinedQuery,才能逐步累积所有的查询条件。
  • 边界情况处理:如果传入的条件列表为空,直接返回空列表,避免后续调用ToList()时出现空引用异常。
  • Union与Concat的选择:根据你的需求决定:
    • Concat(对应SQL的UNION ALL):直接拼接所有符合条件的记录,包含重复项,数据库执行效率更高。
    • Union(对应SQL的UNION):自动对合并后的结果去重,但数据库需要额外处理去重逻辑,性能略低。
  • 单次数据库往返:合并后的combinedQuery是一个完整的查询表达式树,EF Core会将其翻译成包含UNION/UNION ALL的单条SQL语句,当你调用ToList()时,只会发起一次数据库请求,所有合并逻辑在数据库端完成,完全符合你的需求。

另外,如果你后续想优化查询条件的构建,还可以把Where条件封装成表达式树,但当前的写法已经能完美解决你的核心需求了。

内容来源于stack exchange

火山引擎 最新活动