• 使用IDbCommandInterceptor解决EF-CORE-3.x-使用MYSQL时,未正常的生成LIKE查询语句


    使用EF Core 3.x+Mysql 时,如下EF表达式

    var list=await ctx.Set<User>().where(v=>v.Account.Contains("test")).ToListAsync();
    

    生成的语句:

    SELECT 
        `b1`.`id`,
        `b1`.`account`,
         ...
    FROM
        `basis_user` AS `b1`
    WHERE
        LOCATE(CONVERT( 'test' USING UTF8MB4) COLLATE utf8mb4_bin,
                `b1`.`account`) > 0
    
    

    其中 LOCATE(CONVERT( 'test' USING UTF8MB4) COLLATE utf8mb4_bin,`b1`.`account`) > 0是数据库函数操作,数量量大时,会非常慢.
    解决办法:拦截EF生成的语句,将上述函数操作,替换成like

    伪代码如下:

    1:定义拦截器

    public class FmtCommandInterceptor : DbCommandInterceptor, IDbCommandInterceptor
        { 
            public static readonly Regex Regex_Replace_MySql_Like
                    = new Regex(@"LOCATE(CONVERT('(?<v>.+?)' USING utf8mb4) COLLATE utf8mb4_bin, (?<k>`.+`?)) > 0", 
                                RegexOptions.Compiled | RegexOptions.IgnoreCase);
           public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
            {
                command.CommandText = Regex_Replace_MySql_Like.Replace(command.CommandText, " ${k} like '%${v}%' ");
                return base.ReaderExecuting(command, eventData, result);
            }
    
            public override Task<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)
            { 
                command.CommandText = Regex_Replace_MySql_Like.Replace(command.CommandText, " ${k} like '%${v}%' ");  
                return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
            }
        }
    

    2:注册拦截器

                    services 
                    .AddDbContextPool<yearDbContext>(o =>
                    {
                        o.UseMySql(Configuration.GetConnectionString("youdbConfigName"), mySqlOptions =>
                        {
                            mySqlOptions.ServerVersion(new Version(5, 6, 40), ServerType.MySql);
                        }).AddInterceptors(new FmtCommandInterceptor()); 
                    })
    

    有其它场景时,也可以优化上面的正则替换方法,达到替换执行语句的效果

    大家如果有其它办法处理这类问题,也麻烦分享一下

  • 相关阅读:
    CISCO DHCP全攻略详解
    CentOS配置远程日志服务器
    CentOS下的日志切割
    CentOS日志的简单介绍
    H3C Telnet 配置
    CentOS7图形界面与命令行界面切换
    思科4506E做ehterchannel故障排查
    EtherChannel Cisco 端口聚合详解
    算法练习2之单链表求和
    Retrofit2的GsonConverterFactory.create()和RxJava2CallAdapterFactory.create()的实现过程以及执行过程
  • 原文地址:https://www.cnblogs.com/qq156864683/p/12732955.html
Copyright © 2020-2023  润新知