适当的搜索与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());
在这种情况下
.ToLower()
会降低性能吗?我在描述上有
Name
和FullText
的常规索引? 常规指数是否适合我应该使用LINQ或其他方法吗?
是否有办法做到这一点,我可以得到的次数搜索文本发生在名称/描述?
.contains()
?谢谢
我会认真考虑编写一个存储过程来完成这项工作,或者使用SqlQuery
在DbContext中编写原始sql。如果我在写这段代码,我就会这么做。对我来说,EntityFramework和performance从来没有真正地结合在一起。
-
请不要使用较低的,因为它会显著影响性能。
使用下列任意一种:接受StringComparison。OrdinalIgnoreCase
接受StringComparison。CurrentCultureIgnoreCase -
因为你使用的是contains,这将被翻译成'%text%', sql server不太可能使用索引。如果要实现全文搜索,就必须使用存储过程来利用全文搜索的优点。
- 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这将允许你在某些地方更灵活。