【问题标题】:Dynamic LINQ accent insensitive string queries动态 LINQ 重音不敏感字符串查询
【发布时间】:2021-02-06 12:37:30
【问题描述】:

我正在开发一个 C# .Net MVC 应用程序并尝试实现实体字段的通用搜索方法。随着我们的页面不断增长,我不想在每次添加新页面时都编写搜索方法。

为此,我正在使用 Dynamic.Core LINQ 查询:检查它:https://dynamic-linq.net/basic-simple-query 我实现它的方式如下:在视图中的用户输入时,应用程序向控制器发送一个 ajax 请求,告诉它搜索该特定值,然后将新列表显示在前一个列表的位置。

问题是:我可以让它不区分大小写但不区分重音,我想知道是否有人可以帮助我。

这是我的代码:

public static List<T> SearchEntityList<T>(this IQueryable<T> entityList, string searchBy, List<string> fieldsToCheck)
        {

            if (searchBy == null)
                return entityList.ToList();

            searchBy = searchBy.ToLower().RemoveDiacriticsUtil();
            // Dynamic LINQ Library

            string query = "";
            foreach (string str in fieldsToCheck)
            {
                query += str + ".ToString().ToLower().Contains(@0) ||";
            }

            if (query != null)
            {
                // Removes the last "OR" inserted on the foreach here on top
                query = query.Substring(0,query.Length - 3);
                try
                {
                    entityList = entityList.Where(query, searchBy);
                }
                catch (Exception e)
                {
                    // query is wrong, list wont be filtered.
                    return entityList.ToList();
                }
            }
                
            List<T> filteredList = entityList.ToList(); ;
            return filteredList;
        }

该方法接收代表要检查的字段的字符串列表,例如:“用户名” 然后构建一个字符串查询并使用数据库进行检查。

此代码按预期工作并且不区分大小写,现在我想添加不区分重音的代码。

我修改了这一行

query += str + ".ToString().ToLower().Contains(@0) ||";

这个

query += str + "Collate(" + str + ".toString(), \"SQL_Latin1_General_CP1_CI_AI\").Contains(@0) ||";

现在我无法让它工作。 收到此错误:

"No applicable method 'Collate' exists in type '...'"

我测试了很多其他东西,例如 RemoveDiacritics 等。但它们不适用于动态字符串 linq 查询...

想知道是否有人已经遇到过同样的问题。谢谢!

【问题讨论】:

    标签: c# asp.net-mvc entity-framework ef-code-first linq-to-entities


    【解决方案1】:

    你在正确的轨道上。 在我们使用它之前,您需要为动态 linq 注册您的自定义扩展方法:

        // Registration for the default custom type handler
        [DynamicLinqType]
        public static class MyExtensions
        {
            // taken from: https://stackoverflow.com/questions/359827/ignoring-accented-letters-in-string-comparison/368850
            public static string RemoveDiacritics(this string text)
            {
                return string.Concat(
                    text.Normalize(NormalizationForm.FormD)
                        .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
                                     UnicodeCategory.NonSpacingMark)
                ).Normalize(NormalizationForm.FormC);
            }
        }
    
        public static class Entry
        {
            public static void Main(string[] args)
            {
                // your input
                var query = "éè";
    
                // clean it using your extension method
                var cleanQuery = query.RemoveDiacritics();
    
                // a test set for this demo
                IQueryable<string> testSet = new EnumerableQuery<string>(new List<string>()
                {
                    "soméè", "tèèst", "séét", "BBeeBB", "NoMatchHere"
                });
                
                var results = testSet.Where("it.RemoveDiacritics().Contains(@0)", cleanQuery);
                Debug.Assert(results.Count() == 4);
            }
        }
    

    【讨论】:

    • 除非我从问题中了解到,构建的 linq 查询是针对数据库而不是在内存中运行的。
    • 嗯,那将是一个问题。但是 ToString 和 ToLower 将如何工作呢?
    • 取决于 linq 提供程序,这在问题中没有提及。例如对于实体框架,ToString() 可能会被忽略,ToLower() 处理得很好(转换为适当的 sql 函数调用)。
    • 我正在使用实体框架是的,Tolower 被转换为适当的 sql 函数调用,是的...
    • 好的,更多(可能不是最佳)解决方案是在数据库中添加一个“可搜索”字段,或者在搜索之前提取所有字段。 “最佳”解决方案是在 EF 或任何 OP 正在使用的函数中修补一个函数。
    猜你喜欢
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 2012-01-28
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多