4

Closed

Slow performance of EfRepository.GetById()

description

Hi team,

Any particular reason why we are using DbSet.Find() in EfRepository.GetById()?
public virtual T GetById(object id)
{
    return this.Entities.Find(id);
}
I've tried on a project where we have 10K orders where StoreService.GetStoreById() and CurrencyService.GetCurrencyById() is running very slow. After a profiling in Visual Studio, it turned out that EfRepository.GetById() is causing the slowness.

I then change to Enumerable.FirstOrDefault() and the performance is greatly improved (about 3 - 4 seconds faster).

There's a post on StackOverflow: http://stackoverflow.com/questions/11686225/dbset-find-method-ridiculously-slow-compared-to-singleordefault-on-id/11688189#comment34876113_11688189 that talks about the slowness of DbSet.Find():
Find calls DetectChanges internally, SingleOrDefault (or generally any query) doesn't. DetectChanges is an expensive operation, so that's the reason why Find is slower (but it might become faster if the entity is already loaded into the context because Find would not run a query but just return the loaded entity).
I believe we can safely change DbSet.Find() in EfRepository.GetById() to Enumerable.FirstOrDefault(), unless there's any special feature we need from DbSet.Find()?

But "Find" won't call database if a record is already loaded. We should check whether FirstOrDefault calls database twice if we call this method for same entity and ID twice
Closed May 24 at 8:41 AM by AndreyMaz
"Find" won't call database if a record is already loaded. "FirstOrDefault" calls database twice if we call this method for same entity and ID twice. "FirstOrDefault" can add a lot of extra DB calls.

And try-finally and this AutoDetectChangesEnabled could bring some unexpected results.

Anyway "Find" method is not called so often

comments