EF 与 SharpRepository 中流畅查询的性能问题

Performance issue with fluent query in EF vs SharpRepository

我在使用 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 在使用 books 之前不会真正做任何事情(最后一行),然后它将编译一个查询,该查询将 select 只有一小部分数据匹配来自数据库的年份和作者。

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

我是不是误解了什么,有什么办法解决这个问题吗?

Ivan Stoev 提供了这个答案:

"The problem is that most of the repository methods return IEnumerable. Try repo.AsQueryable(). "

您可以使用 repo.AsQueryable() 但这样做会失去 SharpRepository 可以提供的一些功能,例如缓存或您正在使用的 aspects/hooks。它基本上将您带出通用回购层,让您使用底层的 LINQ 提供程序。它肯定有它的好处,但在您的情况下,您可以有条件地构建谓词并将其传递给 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