0

我在使用 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().... 但它的工作方式相同。

我在这里误解了什么,有没有办法解决这个问题?

4

2 回答 2

1

Ivan Stoev 提供了这个答案:

“问题是大多数存储库方法都返回 IEnumerable。试试 repo.AsQueryable()。”

于 2017-09-16T17:01:32.680 回答
1

您可以使用 repo.AsQueryable() 但这样做会丢失 SharpRepository 可以提供的一些功能,例如缓存或您正在使用的方面/挂钩。它基本上将您带出通用 repo 层,并允许您使用底层 LINQ 提供程序。它肯定有它的好处,但在您的情况下,您可以有条件地构建 Predicate 并将其传递给 FindAll 方法。

您可以通过构建表达式谓词或使用规范来做到这一点。使用 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

于 2017-09-18T05:07:57.147 回答