【问题标题】:.net How to make a search method non case sensitive?.net 如何使搜索方法不区分大小写?
【发布时间】:2014-06-17 21:05:20
【问题描述】:

在我的 MVC Web 应用程序中,我正在创建一个搜索功能,我需要将搜索字符串与我的产品存储库中的对象进行比较 - 但是我如何确保搜索不区分大小写? 我可以在我的搜索字符串上使用 ToLower() - 但是存储库?

控制器:

 public ActionResult Search(string q, int page = 1)
 {
        string search = q.ToLower();
        int productCounter = repository.Products.Where(p => p.Name.Contains(search) || p.Description.Contains(search)).Count();

            ProductsListViewModel model = new ProductsListViewModel
            {
                Products = repository.Products
                .Where(p => p.Name.Contains(search) || p.Description.Contains(search))
                .OrderBy(p => p.ProductID)
                .Skip((page - 1) * PageSize)
                .Take(PageSize),
                PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = PageSize,
                    TotalItems = productCounter == 0 ? 0 : productCounter
                }
            };
        return View("List", model);
    }

【问题讨论】:

标签: entity-framework asp.net-mvc-5 repository-pattern


【解决方案1】:

你可以替换这个:

p.Name.Contains(search)

用这个:

p.Name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0

【讨论】:

  • 真的吗? EF 查询中的 IndexOf。或者您有 EF Query.ToList() 并在其上应用 IndexOf 吗?巨大的差异。我刚刚在 EF 6.1 上进行了测试以进行检查。轰炸我的版本。 Docu 认为这是不可能的 ...msdn.microsoft.com/en-us/library/bb738550
【解决方案2】:

您可以使用 IndexOf 来访问 In memory collections 中的 IgnoreCase。 将此应用于 EF 提供程序方案时,您可能会感到失望。 这是正确标记的 EF 吗?

EF Provider 规范不使用 IndexOf。 就此而言,也不支持 Contains(str,comparer)。

Supported Linq to Entities features

如果将 SQLServer 与 EF 一起使用,则原始问题由列排序规则属性控制。例如SQL_Latin1_General_CP1_CI_AS 不区分大小写的拉丁文。

如果您首先拥有 DB,则您可以在 DB 级别控制排序规则。

这里解释得很好...LINQ to Entities case sensitive comparison

如果首先使用代码,则使用默认的 sql server db 排序规则。 有关默认排序规则的更多信息Set database collation in Entity Framework Code-First Initializer

【讨论】:

  • 我有一个 EF 存储库,使我的产品成为 IEnumerable。对此使用 IndexOf 时,它似乎工作正常。
  • @MacLuc 啊,最后看来您使用了错误的方法。您在过滤之前将所有内容都拉入内存。正如菲尔在评论中解释的那样,这是非常低效的。您的存储库应返回 IQueryable 并应在内部使用。
【解决方案3】:

您可以使用 Invariant Culture 并通过使用 Length 来稍微增强查询:

 public ActionResult Search(string q, int page = 1)
    {
        string s;
        string search = q.ToUpperInvariant();
        int productCounter = repository.Products.Where(p => p.Name.ToUpperInvariant().Contains(search) || p.Description.ToUpperInvariant().Contains(search)).Count();
        int searchlength = search.Length;
        ProductsListViewModel model = new ProductsListViewModel
        {
            Products = repository.Products
            .Where(p => (p.Name.Length >= searchlength && p.Name.ToUpperInvariant().Contains(search)) || (p.Description.Length >= searchlength && p.Description.ToUpperInvariant().Contains(search)))
            .OrderBy(p => p.ProductID)
            .Skip((page - 1) * PageSize)
            .Take(PageSize),
            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = PageSize,
                TotalItems = productCounter == 0 ? 0 : productCounter
            }
        };
        return View("List", model);
    }

【讨论】:

  • 如果长度已经小于搜索那么你为什么要搜索?在长字符串中,它会过滤得更快。
  • 不好的建议。 ToUpperInvariant 不能翻译成 SQL,在过滤之前转换数据库值是个坏主意。它禁用索引。
  • 他在哪里提到他正在搜索数据库?存储库也可以是基于对象的。
  • 查询是被翻译成 SQL 的表达式树。 db 引擎完成了真正的工作。
  • 使用StringComparison.OrdinalIgnoreCase 部分? EF 是如何翻译的?
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 2020-01-30
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多