EF与SharpRepository

时间:2017-09-16 14:19:55

标签: entity-framework fluent sharp-repository

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

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

2 个答案:

答案 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