编写在EF Core中不区分大小写的搜索查询?

我想问一个有关SQL Server和EF Core的问题。数据库中的排序规则是Latin1_CI_AS,我想编写一个包含土耳其语字符的搜索查询。

在数据库中,“人员”表中有一条名为“SELİM”的记录。当我在EF Core中编写这样的查询时:

    public async Task<IList<PersonnelGetDto>> Get(PersonnelGetPayload payload)
        {
           if (payload.Name != null)
                query = query.Where(x => x.Name.Contains(payload.Name)); 
        }

如果我的搜索条件是“ selim”,则该列表为空。

由于我们的应用程序是多语言的,因此我没有机会将数据库中的排序规则更改为土耳其语。我认为其他语言也会有问题。还是我错了?

我也写了字符串扩展名。但是,将LINQ查询转换为SQL时,所有记录都会到达服务层,因为LIKE运算符未分配WHERE子句。在sql端运行此条件非常重要。如果我将所有数据集带到服务层并进行查询,那将花费我很多钱。

当我在数据库中键入查询时,可以解决此问题:

SELECT * FROM Personnel WHERE Name LIKE 'selim' COLLATE Turkish_CI_AS

我认为,如果我可以在EF Core上进行整理,就可以解决问题。

chenglong676 回答:编写在EF Core中不区分大小写的搜索查询?

您要紧追EF.Functions.Like,如果还没有,则需要添加using Microsoft.EntityFrameworkCore;。然后,您的查询将类似于:

query.Where(x => EF.Functions.Like(x.Name,$"%{payload.Name}%"))

这直接转换为生成的SQL语句中的LIKE运算符。并非每个DBMS都可用,但是只要您添加了Microsoft.EntityFrameworkCore.SqlServer,您就可以准备就绪(假设您的问题已正确标记)。

,

我已经测试过类似的功能,但不能如op所述正确。因此,只剩下一个选择。这是创建一个拦截器并实现自定义逻辑。我创建了一个如下示例:

   public class Suffixes
    {
        public const string Collate = "--Collate";
    }

    public class CollationDbCommandInterceptor : DbCommandInterceptor
    {
        private const string CollateSyntax = " collate turkish_ci_as";

        public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command,CommandEventData eventData,InterceptionResult<DbDataReader> result)
        {
            var args = command.Parameters.OfType<DbParameter>()
                           .Where(t => t.DbType == DbType.String && t.Value.ToString().EndsWith(Suffixes.Collate)).ToList();
            if (args.Count <= 0)
                return base.ReaderExecuting(command,eventData,result);

            foreach (var parameter in args)
            {
                parameter.Value = parameter.Value.ToString().Replace(Suffixes.Collate,"");
                var equality = $"= {parameter.ParameterName}";

                var ixs = AllIndexesOf(command.CommandText,equality);

#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
                foreach (var eq in ixs)
                {
                    command.CommandText = command.CommandText.Insert(eq+equality.Length,CollateSyntax);

                }
#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities

            }



            return base.ReaderExecuting(command,result);
        }

        private static IEnumerable<int> AllIndexesOf(string str,string value)
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("the string to find may not be empty",nameof(value));
            var indexes = new List<int>();
            for (var index = 0; ; index += value.Length)
            {
                index = str.IndexOf(value,index);
                if (index == -1)
                    return indexes;
                indexes.Insert(0,index);
            }
        }
    }

配置:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
               ....  
                optionsBuilder.AddInterceptors(new CollationDbCommandInterceptor());
                ....
            }
        }

用法:

var kadayif = $"kadayıf{Suffixes.Collate}";
var william = $"Wİlliam{Suffixes.Collate}";            
var auths = ctx.Authors.Where(t =>   t.FirstName == william ||t.LastName == kadayif).ToList(); 
// returns William Shakespeare and Abuzer Kadayıf

逻辑是创建一个拦截器,该拦截器在查询中传递的sql参数中查找特定的后缀。将查询特定的排序规则注入最终的sql命令文本中。我试图介绍一些高级方案,例如参数重用。可能需要更多改进。

请注意,此示例适用于Entity Framework Core 3.0,这是拦截器引入的版本。早期的ef核心版本中的拦截有些技巧。您可以参考this链接以获取更多信息。

本文链接:https://www.f2er.com/3011181.html

大家都在问