4

我需要通过数据库中的产品搜索产品,并且我希望以正确的方式进行设置,以便在有很多行(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. 我有一个关于描述的常规Name索引FullText?这是否合适,并且常规索引是否可以很好地使用.contains()

  3. 我应该使用 LINQ 还是其他方法?

  4. 有没有办法做到这一点,我可以获得搜索文本在名称/描述中出现的次数?

谢谢

4

3 回答 3

1

就我而言,我不想使用存储过程。我正在使用实体框架,这就是我想要使用的!

看看这个方法对你有没有帮助。

    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);
    }

它是由 Microsoft 创建但未包含在框架中的动态 LINQ dll 实现的。动态 LINQ这将使您在某些方面更加灵活。

于 2013-03-28T21:50:37.557 回答
1
  1. 请不要使用较低的,因为它会显着影响性能。
    使用以下方法之一:

    StringComparison.OrdinalIgnoreCase
    StringComparison.CurrentCultureIgnoreCase

  2. 由于您使用的是包含,它将被翻译为“%text%”,因此 sql server 不太可能使用索引。如果实现全文搜索,则必须使用存储过程来利用全文搜索的优势。

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

一般来说,如果您使用的是最新的实体框架,您应该会获得相当不错的性能,因为它们在版本 5 中有一些显着的性能改进。

于 2013-03-28T21:40:19.360 回答
1

我会认真考虑编写一个存储过程来执行此操作,或者在 DbContext 中使用SqlQuery. 如果我正在编写这段代码,那就是我会做的。对我来说,EntityFramework 和 performant 从来没有真正走到一起。

于 2013-03-28T21:42:47.017 回答