This document covers some basics of improving performance of Entity Framework using LINQ. You can also refer the same at http://ankushasthana.blogspot.jp/2014/02/basics-for-performance-improvement-in.html.
More than Just Lines on a Map: Best Practices for U.S Bike Routes
Basics for performance improvement of Entity Framework using LINQ
1. Basics for performance improvement in Entity
Framework using LINQ
1. Remove all for each loops for accessing and manipulating data using entity
framework. Instead use LINQ to SQL/ENTITIES.
a. LINQ though adds slight additional overhead over for each loop when dealing
with very large amount of data.
b. But LINQ to SQL or Entity framework has a better performance as LINQ
query gets directly converted to T-SQL.
c. LINQ provides shorter better readable and maintainable code.
d. Basic facts –
i. LINQ gets executed when it gets enumerated by foreach loop.
ii. LINQ gets executed by collection operations like ToArray(), ToList(),
ToDictionary().
2. Disable change tracking for entity if not needed.
a. Whenever we are only reading data (no modification involved) then we should
disable tracking of changes to entity.
b. This prevents unnecessary entity caching and management.
unitResponse = (from unitRow in entities.Units.AsNoTracking()
where unitRow.UnitID == unitId
selectnew PocoEntities.Unit()
{
ID = unitRow.UnitID,
Level = unitRow.Level,
Theme = unitRow.Theme
});
3. Avoid fetching fields that are not required.
a. For example I want to get only unit id, level and theme fields of the Unit table
from DB.
b. So I fetch only those fields in my LINQ query instead of selecting the entire
unitRow variable in the query.
unitResponse = (fromunitRowin entities.Units.AsNoTracking()
where unitRow.UnitID == unitId
selectnew PocoEntities.Unit()
{
ID = unitRow.UnitID,
Level = unitRow.Level,
Theme = unitRow.Theme
2. });
4. Try to write LINQ in such a way that there is a single round trip while executing the
query.
a. Code with multiple round trips.
foreach (Customer c in Customers)
foreach (Purchase p in c.Purchases)
// Another SQL round-trip
Console.WriteLine (c.Name + " spent " + p.Price);
b. Code with single round trip.
from c in Customers
select
from p in c.Purchases
selectnew { c.Name, p.Price }
5. Avoid using Contains.
a. When using LINQ to SQL avoid using contains.
b. This gets converted to WHERE IN clause in SQL. This leads to performance
degrades with large data sets.
c. In WHERE IN sub query gets executed first, the result is indexed and made
distinct.The output is then joined tofirst part of the query.
d. But at the same time we can use Contains in LINQ to entities.
6. For filtering data use DataLoadOptions.
a. DataLoadOptions in LINQ allows immediate loading and filtering of related
data. It allows you load related objects so this removes the need for firing a
sub query every time you ask for related objects.
b. If you have written code like below then each time inner loop fires a query on
DB. This in turn decreases performance.
foreach (Customer c in Customers)
{
Console.WriteLine (c.ID + " " + c.Name);
foreach (Purchase p in c.Purchases)
Console.WriteLine (" - purchased a " + p.Description);
}
c. Using DataLoadOptions loadrelated objects.
var options = new DataLoadOptions();
options.AssociateWith <Customer> (c => c.Purchases.Where (p => p.Price
>1000));
LoadOptions = options;
foreach (Customer c in Customers)
{
Console.WriteLine (c.ID + " " + c.Name);
foreach (Purchase p in c.Purchases)
3. Console.WriteLine ("
- purchased a " + p.Description);
}
7. Eager loading means immediate loading of all the related objects when you query for
an object.This can be done in two ways:a. DataLoadOptions (LINQ to SQL) – This creates a single SQL query for
querying two related tables.
var options = new DataLoadOptions();
options.LoadWith <Customer> (c => c.Purchases);
LoadOptions = options;
foreach (Customer c in Customers)
{
Console.WriteLine (c.ID + " " + c.Name);
foreach (Purchase p in c.Purchases)
Console.WriteLine (" - purchased a " + p.Description);
}
b. Using include method (LINQ to Entity framework) –This creates a single
query for related objects by using a SQL join.
List<Customer> customers = db.Customer.Include("Purchases").ToList();
8. In order to debug and optimize LINQ queries I used the below two mentioned tools:a. LINQPad – This helps us execute and debug LINQ queries. It also helps us in
converting the LINQ queries to SQL queries. This way we can validate the
performance of our LINQ query.
b. Linqer – This helps us in converting our SQL queries to LINQ. So we can
write our own optimized SQL queries and convert them to LINQ.
9. Areas to explore :a. Use Pre-Generating Views to reduce response time for first request.
b. Use Compiled Query wherever needed.
http://ankushasthana.blogspot.jp/2014/02/basics-for-performance-improvement-in.html.