Entity Framework (EF), Microsoft's ORM answer to nHibernate, is an excellent tool. I've used it many times in many projects. It's easy to get started and set up, it's versatile and has good support. Unfortunately, as with every other tool, there are pitfalls. The larger a project gets, the harder it becomes to use EF straight out-of-the-box. As your objects and relationships grow, your queries need to become more intelligent. More refined. There are many ways to mitigate performance issues, BDD, multiple contexts, query optimization, AutoMapper, etc. I could probably do another post or posts just on this subject! And remember:
Just because LINQ supports it, it doesn't mean it's a good idea
Today I'll show you how to quickly make performance improvements in your EF query implementation. There are 2 major benefits in this approach:
- You don't have to make changes to your data model
- It's quick and easy to put in place
However, as with everything else, there is a downside too. The suggested solution applies only to read-only operations. This is not the end of the world though, as typical database workflows have a standard format. I will use a typical web page as an example:
1. Query Data -> 2. Display Data -> 3.Select item to interact with -> 4. Edit -> 5. Save
EF in the context of web operations is special. Developers tend to forget that EF operates in a disconnected context when used on the web. Each operation (1-5) is disconnected as far as EF is concerned. Each time you have to fetch/bind your object graph to perform the necessary operation. Consequently, it's easy to optimize certain parts of the above workflow using the read-only dbContext
. Parts 1 and 3 are prime candidates. The read-only dbContext
takes advantage of the following configuration settings:
- Disable Lazy Loading:
Configuration.LazyLoadingEnabled = false;
- Disable AutoDetectChanges:
Configuration.AutoDetectChangesEnabled = false;
- Disable Proxy Creation:
Configuration.ProxyCreationEnabled = false;
- Disable Entity Caching using the
IQueryable AsNoTracking()
method
Show me the code!
I've included the sample ReadonlyDbContext
for reference below:
The ReadonlyDbContext
class should derive from your base DbContext
. 2 things are important:
- The
SetConfigurationOptions()
method where we set up the properties I mentioned earlier. - Calling
Save()
will throw an exception to guard against unwanted behavior
You use the query-optimized dbContext like this:
I hope this will help you improve your EF queries but remember that this is only one of the many performance optimization tweaks you can do. Make sure you investigate all available options and don't be afraid to refactor your code. You want your DAL to be as robust and efficient as possible.
Related posts
- Logging and tracing with Entity Framework 6
- Generic Repository with Entity Framework
- The specified type member 'Date' is not supported in LINQ to Entities Exception - Entity Framework