Tuesday 18 November 2014

Tips to improve Entity Framework Performance

  Version Support : EF 4.1, 5.0+
 
Keywords : performance considerations for entity framework 5, tips to improve linq to entity query performance, tips to improve linq query performance
LINQ to Entity is a great ORM for querying and managing database. It offers a lot of things, so it is mandatory to know about performance of it. These are right up to a certain point as LINQ comes with its own penalties. There are some tips and tricks that we should keep in mind while desiging and query database using entity framework ORM. Here is a list of some tips that I would like to share with you.
  1. Avoid to put all the DB Objects into One Single Entity Model

    Entity Model specifies a single unit of work, not all our database. If we have many database objects that are not connected to one another or these(log tables, objects used by batch processes,etc.) are not used at all. Hence these objects are consuming space in the memory and cause performance degrades. So try to make separate entity models of related database objects.
  2. Disable change tracking for entity if not needed

    Whenever you retrieve the data only for reading purpose, not for modification then there is no need of object tracking. So disable object tracking by using MergeOption as below:
    1. NorthwindDataContext context = new NorthwindDataContext() context.tblCities.MergeOption = MergeOption.NoTracking;
    This option allow us to turn off the object cache and unnecessary identity management of the objects.
  3. Use Pre-Generating Views to reduce response time for first request

    When the object of ObjectContext is created first time in the application, the entity framework creates a set of classes that is required to access the database. This set of classes is called view and if your data model is large then creating the view may delay the web application response to the first request for a page. We can reduce this response time by creating view at compile time by using T4 template or EdmGen.exe command-line tool.
  4. Avoid fetching all the fields if not required

    Avoid fetching not required fields from the database. Suppose I have table of Customer with 20 fields and I am interested only in three fields - CustomerID, Name, Address then fetch only these three fields instead of fetching all the fields of the Customer table.
    1. //Bad Practice
    2. var customer =
    3. (from cust in dataContext.Customers
    4. select cust).ToList();
    5. //Good Practice
    6. var customer =
    7. (from cust in dataContext.Customers
    8. select new {
    9. customer. CustomerID,
    10. customer.Name,
    11. customer.Address
    12. }). ToList ();
  5. Choose appropriate Collection for data manipulation

    In linq we have Var, IEnumerable, IQueryable, IList type collection for data manipulation. Each collection has its importance and performance impact on the query, so beware of using all these collection for data manipulation. For learning difference among all these collection refer my articles IEnumerable VS IQueryableIEnumerable VS IList and Var VS IEnumerable.
  6. Use Compiled Query wherever needed

    Make a query to compiled query if it is frequently used to fetch records from the database. This query is slow in first time but after that it boost the performance significantly. We use Compile method of CompiledQuery class for making compiled query.
    Suppose you required to retrieve customers details again and again based on city then make this query to compiled query like as
    1. // create the entity object
    2. NorthwindEntities mobjentity = new NorthwindEntities();
    3. //Simple Query
    4. IQueryable lstCus = from customer in mobjentity.tblCustomers
    5. where customer.City == "Delhi"
    6. select customer;
    7. //Compiled Query
    8. Func> compiledQuery
    9. = CompiledQuery.Compile>(
    10. (ctx, city) =>from customer in ctx.Customers
    11. where customer.City == city
    12. select customer);
    In above query we are passing the string parameter city for filtering the records. For more about anonymous method.
  7. Retrieve only required number of records

    When we are binding data to grid or doing paging, retrieve only required no of records to improve performance. This can achieved by using Take,While and Skip methods.
    1. // create the entity object
    2. NorthwindEntities mobjentity = new NorthwindEntities();
    3. int pageSize=10,startingPageIndex=2;
    4. List lstCus = mobjentity.tblCustomers.Take(pageSize)
    5. .Skip(startingPageIndex * pageSize)
    6. .ToList();
  8. Avoid using Contains

    In LINQ, we use contains method for checking existence. It is converted to "WHERE IN" in SQL which cause performance degrades.
  9. Avoid using Views

    Views degrade the LINQ query performance costly. These are slow in performance and impact the performance greatly. So avoid using views in LINQ to Entities.
  10. Debug and Optimize LINQ Query

    If you want to debug and optimize your query then LINQ Pad is a great tool for this purpose. I am a big fan of LINQ Pad. It is very useful for query construction, debugging and optimization.
    1. IQueryable lstCus = from customer in mobjentity.tblCustomers
    2. where customer.City == "Delhi"
    3. select customer;
    4. lstCus.Dump();
    Dump method of LINQ Pad give the result of above query in the result window.
Summary
I hope you will enjoy these tips and tricks while programming with LINQ to Entity. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

7 comments:

  1. Do not collect all data while binding data to a data grid. For example if we have a data grid on a page and we only show 10 records on the screen, so do not fetch all records from the database, as in:

    AdventureWorksEntities e = new AdventureWorksEntities();
    int pageSize = 30, startingPageIndex = 3;
    List lstemp = e.EmployeeMasters
    .Take(pageSize)
    .Skip(startingPageIndex * pageSize).ToList()

    ReplyDelete
  2. //Uses string notation - lots of typos!
    //var posts = context.Posts
    // .Include("Author")
    // .ToArray();

    //Uses lambda notation - Intellisense and easy refactoring = love
    //Note: include System.Data.Entity to use.
    var posts = context.Posts
    .Include(p => p.Author)
    .ToArray();

    var model = (from post in posts
    select new PostsViewModel
    {
    Title = post.Title,
    Url = post.Url,
    AuthorName = post.Author.Name,
    AuthorTwitterHandle = post.Author.TwitterHandle
    }).ToArray();

    public class Post : EntityBase
    {
    public string Title { get; set; }
    public string Url { get; set; }
    public virtual Author Author { get; set; }
    }

    public class Author : EntityBase
    {
    public Author()
    {
    Posts = new Collection();
    }

    public string Name { get; set; }
    public string TwitterHandle { get; set; }
    public virtual ICollection Posts { get; set; }
    }

    ReplyDelete
  3. Use Compiled Query

    If you are using Entity Framework 4.1 and below, you must use a compiled query. The Compiled Query class provides compilation and caching of queries for reuse. The Entity Framework 5.0 supports a new feature called Auto-Compiled LINQ Queries. With EF 5.0, LINQ to Entity queries are compiled automatically and placed in EF's query cache, when executed.

    static Func> getEmpList = (
    CompiledQuery.Compile((AdventureWorksEntities db) =>
    db.EmployeeDetails
    ));

    AdventureWorksEntities e = new AdventureWorksEntities1();
    List empList = getEmpList(e).ToList();

    ReplyDelete
  4. Disable change tracking for entity if not needed

    In the Entity Framework, the context is responsible for tracking changes in entity objects. Whenever we are only reading data, there is no need to track the entity object. We can disable entity tracking using the MergeOption, as in:

    AdventureWorksEntities e = new AdventureWorksEntities();
    e.EmployeeMasters.MergeOption = System.Data.Objects.MergeOption.NoTracking;

    ReplyDelete
  5. Be *very* careful when putting entities in ViewState
    Avoid this as best you can, if you have to maintain objects in this fashion, try to make wrapper classes. Having the full entities in viewstate tend to be fairly huge compared to the relevant information that you want to keep track of, not to mention that if you have relations included, this will grow even bigger.

    ReplyDelete
  6. Performance Optimization with Pre-generate Entity Framework Views

    In Global.asax, create a function RegenerateEntityFrameworkViews().
    In Application_Start(), call above function to generate artifacts for your context “Context.ssdl”, “Context.csdl”, “Context.msl”.
    Use EdmGen tool to generate views from above artifacts. I need to do it from the VS Command prompt. Here is the command I use to generate views: EdmGen /nologo /language:CSharp /mode:ViewGeneration /inssdl:Context.ssdl /incsdl:Context.csdl /inmsl:Context.msl /outviews:Model1.Views.cs
    Add the generated file to the project under Models then compile.
    Run RegenerateEntityFrameworkViews function every time when database changed, otherwise comment it out.

    ReplyDelete
  7. Good evening, a quick note to tell you that I love your blog, so I do not deprive myself! Thank you for all the work that this represents and for all the pleasure that I find in it.

    Voyance gratuite en ligne par mail en direct

    ReplyDelete

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...