我在使用SharpRepository时遇到了一些性能问题,在使用SQL Query Profiler后我发现了原因。
使用EF我可以做这样的事情:
var books = db.Books.Where(item => item.Year == '2016');
if (!string.IsNullorEmpty(search_author))
books = books.Where(item => item.Author.Contains(search_author);
return (books.ToList());
在使用书籍(最后一行)之前,EF不会真正做任何事情,然后它将编译一个查询,该查询将只从数据库中选择匹配年份和作者的一小组数据。
但SharpRepository会立即评估图书,所以:
var books = book_repo.Books.FindAll(item => item.Year == '2016');
if (!string.IsNullorEmpty(search_author))
books = books.Where(item => item.Author.Contains(search_author);
return (books.ToList());
将在第一行编译一个类似“select * from books where Year =='2016'”的查询,并从数据库中获取所有这些记录!然后在第二行,它将在C#代码中搜索作者...当使用大型数据库时,这种行为可能是性能的主要差异,并且它解释了为什么我的查询超时......
我尝试使用repo.GetAll()。Where()而不是repo.FindAll()....但它的工作方式相同。
我在这里误解了什么,有没有解决这个问题的方法?
答案 0 :(得分:1)
Ivan Stoev提供了这个答案:
"问题是大多数存储库方法都返回IEnumerable。尝试repo.AsQueryable()。 "
答案 1 :(得分:1)
你可以使用repo.AsQueryable()但是这样做会丢失SharpRepository可以提供的一些功能,比如你正在使用的缓存或方面/钩子。它基本上将您带出通用repo层,并允许您使用底层的LINQ提供程序。它肯定有它的好处,但在你的情况下,你可以有条件地构建谓词并将其传递给FindAll方法。
您可以通过构建Expression谓词或使用规范来完成此操作。使用Linq表达式并不总是感觉干净,但您可以这样做。或者您可以使用SharpRepository中内置的规范模式。
ISpecification<Book> spec = new Specification<Book>(x => x.Year == 2016);
if (!string.IsNullorEmpty(search_author))
{
spec = spec.And(x => x.Author.Contains(search_author));
}
return repo.FindAll(spec);
有关规格的详细信息,请参阅此处:https://github.com/SharpRepository/SharpRepository/blob/develop/SharpRepository.Samples/HowToUseSpecifications.cs