适当的搜索与Linq,实体框架和数据库索引

本文关键字:框架 实体 数据库 索引 Linq 搜索 | 更新日期: 2023-09-27 18:06:36

我需要通过数据库中的产品搜索产品,并且我希望以正确的方式设置此设置,以便当有很多行(1,000,000)时我可以具有可靠的性能。我对LINQ和EF有一定的经验,但从未编写过任何搜索算法,我有以下代码,但只是有一些挥之不去的问题。

context.products.Where(i => i.Name.ToLower().Contains(searchText.ToLower());

我还需要搜索描述。

context.products.Where(i => i.Description.ToLower().Contains(searchText.ToLower());
  1. 在这种情况下.ToLower()会降低性能吗?

  2. 我在描述上有NameFullText的常规索引?

  3. 常规指数是否适合.contains() ?
  4. 我应该使用LINQ或其他方法吗?

  5. 是否有办法做到这一点,我可以得到的次数搜索文本发生在名称/描述?

谢谢

适当的搜索与Linq,实体框架和数据库索引

我会认真考虑编写一个存储过程来完成这项工作,或者使用SqlQuery在DbContext中编写原始sql。如果我在写这段代码,我就会这么做。对我来说,EntityFramework和performance从来没有真正地结合在一起。

  1. 请不要使用较低的,因为它会显著影响性能。
    使用下列任意一种:

    接受StringComparison。OrdinalIgnoreCase
    接受StringComparison。CurrentCultureIgnoreCase

  2. 因为你使用的是contains,这将被翻译成'%text%', sql server不太可能使用索引。如果要实现全文搜索,就必须使用存储过程来利用全文搜索的优点。

  3. Linq总是比手写的sql语句慢。我在dapper.net网站上看到了一些性能指标

一般来说,如果你使用的是最新的实体框架,你应该会得到一个相当好的性能,因为他们在版本5中有一些显著的性能改进。

在我的例子中,我不想使用存储过程。我正在使用实体框架,这就是我想使用的!

看看这个方法是否对你有帮助。

    public static IQueryable<T> LikeOr<T>(this IQueryable<T> source, string columnName, string searchTerm)
    {
        IEnumerable<string> words =
            searchTerm.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries).Where(x => x.Length > 1);
        var sb = new StringBuilder();
        for (int i = 0; i < words.Count(); i++)
        {
            if (i != 0)
                sb.Append(" || ");
            sb.Append(string.Format("{0}.Contains(@{1})", columnName, i));
        }
        return source.Where(sb.ToString(), words.ToArray());
    }

上面所有的方法都是建立一个SQL字符串,然后将它传递给一个动态LINQ Where方法。在较高的层次上,所有这些都允许您仅在需要时使用直接sql,而不是用sql编写整个查询。它是这样命名的:

    public List<Book> SearchForBooks(string phrase)
    {
        return _db.Books.Include(x=> x.Images).LikeOr("Title", phrase).OrderBy(x => x.Title)
            .Take(6).Select(x => x).ToList()
            .OrderByCountDescending("Title", phrase);
    }

这是由微软创建的动态LINQ dll实现的,但不包括在框架中。动态LINQ这将允许你在某些地方更灵活。