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

C# 在EF Core中编写不区分大小写的搜索查询?,c#,sql-server,.net-core,entity-framework-core,case-insensitive,C#,Sql Server,.net Core,Entity Framework Core,Case Insensitive,我想问一个关于SQL Server和EF Core的问题。数据库中的排序规则是Latin1\u CI\u AS,我想编写一个包含土耳其语字符的搜索查询 在数据库中,“人员”表中有一条名为“SELİM”的记录。当我在EF Core中编写这样的查询时: public async Task<IList<PersonnelGetDto>> Get(PersonnelGetPayload payload) { if (payload.N

我想问一个关于SQL Server和EF Core的问题。数据库中的排序规则是
Latin1\u CI\u 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)); 
        }
我想如果我能在EF Core上操作collate,我会解决这个问题。

你要找的,这需要使用Microsoft.EntityFrameworkCore添加
,如果您还没有。然后,您的查询将如下所示:

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

这将直接转换为生成的SQL语句中的
LIKE
运算符。不是每个DBMS都可以使用它,但是只要您添加了,就可以使用它(假设您的问题标记正确)。

我已经测试了类似的函数,但结果并不像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, eventData, 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);
            }
        }
    }
用法:

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核心版本中拦截是一个小把戏。有关更多信息,请参阅链接。

这是否回答了您的问题?不,不是这个。因为İ和我是不同的字母。我尝试了此解决方案,但没有成功。是否使用
indexOf
作为选项
query=query.Where(x=>x.Name.IndexOf(payload.Name,StringComparison.OrdinalIgnoreCase))当我实现这一点时,我遇到了以下错误:“无法将类型'int'隐式转换为'bool'”和“无法将lambda表达式转换为预期的委托类型,因为块中的某些返回类型无法隐式转换为委托返回类型”
…其中(x=>x.Name.IndexOf(payload.Name,StringComparison.OrdinalIgnoreCase)>-1)
嗨,蒂森,谢谢你的关注。在实现您的解决方案时,我启动了sql profiler并观察了对数据库的查询。但我看到“like”不包括在查询中。在sql端运行此条件非常重要。如果我将所有数据集都带到服务层并查询它,这将花费我很多。@SametÖz只要您没有枚举您的值,这将转换为生成的SQL中的LIKE子句。您的问题中没有足够的内容来显示
query
来自何处或它是什么,因此我无法真正说明运行探查器时发生了什么。如果您正试图构建一个复杂的查询,那么您可能需要研究LinqKit,尤其是。
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