You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySql EF Core Provider中Linq查询Contains用法失败求助

解决方案

问题原因

Pomelo.EntityFrameworkCore.MySql 8.0.2 默认未启用原始集合支持,导致无法翻译内存集合的 Any(y => y.Contains(x.ExternalNumber.ToUpper())) 这类组合查询逻辑。


方案一:启用原始集合支持

直接在 DbContext 配置中开启该特性,原查询即可正常运行:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseMySql(
        "你的MySQL连接字符串",
        new MySqlServerVersion(new Version(8, 0, 21)), // 匹配你的MySQL服务版本
        options => options.EnablePrimitiveCollections() // 开启原始集合翻译支持
    );
}

注:该特性在 Pomelo 5.0.0 及以上版本可用,你的 8.0.2 版本完全兼容。


方案二:手动构建OR条件组合查询

如果不想启用原始集合支持,可将内存集合的每个元素转换成独立的过滤条件,再用OR逻辑拼接:

方式1:使用LinqKit简化表达式拼接

先通过 NuGet 安装 LinqKit.Microsoft.EntityFrameworkCore,再重构查询:

// 先处理内存集合,转成List避免多次枚举
var upperStringList = listStringValues.Where(x => x != null).Select(x => x.ToUpper()).ToList();

// 构建外部编号的过滤条件
var externalNumberPredicate = PredicateBuilder.False<Invoice>();
foreach (var value in upperStringList)
{
    var currentValue = value; // 捕获循环变量,避免闭包引用问题
    externalNumberPredicate = externalNumberPredicate.Or(x => currentValue.Contains(x.ExternalNumber.ToUpper()));
}

// 组合最终查询
var query = _ctx.Invoices
    .Where(x => 
        (x.FormatType.FormatTypeCode == FormatTypeCode.ER ||
         x.FormatType.FormatTypeCode == FormatTypeCode.AR ||
         x.FormatType.FormatTypeCode == FormatTypeCode.EA ||
         x.FormatType.FormatTypeCode == FormatTypeCode.AA) &&
        externalNumberPredicate.Invoke(x))
    .AsExpandable(); // LinqKit需要调用此方法解析表达式

方式2:手动拼接表达式树(无需第三方库)

using System.Linq.Expressions;

// 处理内存集合
var upperStringList = listStringValues.Where(x => x != null).Select(x => x.ToUpper()).ToList();

// 初始化条件为false
Expression<Func<Invoice, bool>> externalNumberCondition = x => false;
foreach (var value in upperStringList)
{
    var currentValue = value;
    // 构建单个条件:currentValue.Contains(x.ExternalNumber.ToUpper())
    var parameter = Expression.Parameter(typeof(Invoice), "x");
    var externalNumberUpper = Expression.Call(
        Expression.Property(parameter, nameof(Invoice.ExternalNumber)),
        typeof(string).GetMethod(nameof(string.ToUpper), Type.EmptyTypes)!);
    var containsCall = Expression.Call(
        Expression.Constant(currentValue),
        typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string)})!,
        externalNumberUpper);
    var singleCondition = Expression.Lambda<Func<Invoice, bool>>(containsCall, parameter);
    
    // 合并到总条件(OR逻辑)
    externalNumberCondition = Expression.Lambda<Func<Invoice, bool>>(
        Expression.OrElse(externalNumberCondition.Body, 
            Expression.Invoke(singleCondition, externalNumberCondition.Parameters)),
        externalNumberCondition.Parameters);
}

// 组合查询
var query = _ctx.Invoices
    .Where(x => 
        (x.FormatType.FormatTypeCode == FormatTypeCode.ER ||
         x.FormatType.FormatTypeCode == FormatTypeCode.AR ||
         x.FormatType.FormatTypeCode == FormatTypeCode.EA ||
         x.FormatType.FormatTypeCode == FormatTypeCode.AA) &&
        externalNumberCondition.Invoke(x))
    .AsExpandable();

可选优化:用EF.Functions.Like生成标准SQL

如果希望生成更贴近原生SQL的LIKE语句,可替换Contains为EF.Functions.Like:

var externalNumberPredicate = PredicateBuilder.False<Invoice>();
foreach (var value in upperStringList)
{
    var currentValue = value;
    externalNumberPredicate = externalNumberPredicate.Or(x => 
        EF.Functions.Like(x.ExternalNumber.ToUpper(), $"%{currentValue}%"));
}

内容的提问来源于stack exchange,提问作者SB_84

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 05:30:07