简体   繁体   English

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

[英]Performance issue with fluent query in EF vs SharpRepository

I was having some performance issues using SharpRepository, and after playing around the SQL Query Profiler I found the reason. 我在使用SharpRepository时遇到了一些性能问题,在玩过SQL Query Profiler之后,我找到了原因。

With EF I can do stuff like this: 使用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 will not really do anything until books is used (last line) and then it will compile a query that will select only the small set of data matching year and author from the db. 直到使用完书籍(最后一行),EF才会真正做任何事情,然后它将编译一个查询,该查询将仅从数据库中选择与年份和作者匹配的一小部分数据。

But SharpRepository evaluates books at once, so this: 但是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());

will compile a query like "select * from Books where Year == '2016'" at the first line, and get ALL those records from the database! 将在第一行编译一个查询,例如“从Year =='2016'的书中选择*”,并从数据库中获取所有这些记录! Then at the second line it will make a search for the author within the C# code... That behaviour can be a major difference in performance when using large databases, and it explains why my queries timed out... 然后在第二行它将在C#代码中搜索作者...使用大型数据库时,这种行为可能是性能上的主要差异,并且它解释了我的查询为什么超时的原因...

I tried using repo.GetAll().Where() instead of repo.FindAll().... but it worked the same way. 我尝试使用repo.GetAll()。Where()代替repo.FindAll()....,但是它的工作方式相同。

Am I misunderstanding something here, and is there a way around this issue? 我在这里误解了什么,这个问题有办法解决吗?

Ivan Stoev provided this answer: 伊万·斯托夫(Ivan Stoev)提供了以下答案:

"The problem is that most of the repository methods return IEnumerable. Try repo.AsQueryable(). " “问题在于大多数存储库方法都返回IEnumerable。请尝试repo.AsQueryable()。”

You can use repo.AsQueryable() but by doing that you lose some of the functionality that SharpRepository can provide, like caching or and aspects/hooks you are using. 您可以使用repo.AsQueryable(),但是这样做会丢失SharpRepository可以提供的某些功能,例如缓存或正在使用的方面/挂钩。 It basically takes you out of the generic repo layer and lets you use the underlying LINQ provider. 从根本上讲,它使您脱离了通用存储库层,并可以使用基础LINQ提供程序。 It has it's benefits for sure but in your case you can just build the Predicate conditionally and pass that in to the FindAll method. 它肯定有好处,但是对于您而言,您可以有条件地构建谓词并将其传递给FindAll方法。

You can do this by building an Expression predicate or using Specifications. 您可以通过构建表达式谓词或使用规范来做到这一点。 Working with the Linq expressions does not always feel clean, but you can do it. 使用Linq表达式并不总是很干净,但是您可以做到。 Or you can use the Specification pattern built into SharpRepository. 或者,您可以使用SharpRepository中内置的Specification模式。

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);

For more info on Specifications you can look here: https://github.com/SharpRepository/SharpRepository/blob/develop/SharpRepository.Samples/HowToUseSpecifications.cs 有关规范的更多信息,请参见此处: https : //github.com/SharpRepository/SharpRepository/blob/develop/SharpRepository.Samples/HowToUseSpecifications.cs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM