top of page

Boost Performance in .NET App

Requests from DB can be tracked or untracked. By default, all queries that return model objects from DB are trackable.

When the data context retrieves data from the database, the Entity Framework places the retrieved objects in the cache and monitors changes that occur to those objects until it uses the SaveChanges() or SaveChangesAsync() method, which commits any changes to the database. But we don’t always need to track changes. For example, we just need to display data for viewing.

To prevent the data from being cached, the AsNoTracking() method is used. When AsNoTracking() applied, the data returned from the request is not cached, that is, the request becomes untracked. This means that the Entity Framework does not perform any additional processing and does not allocate additional space for storing objects retаrieved from the database. And therefore, such queries are faster.


Now let’s get down to practice :)

Let’s say we have the following models and data context:

using Microsoft.EntityFrameworkCore;

namespace AsNoTrackinsExample
{
    public class User    
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }    
    }
    
    public class AppDbContext : DbContext    
    {
        public DbSet<User> Users { get; set; }
        protected override void  OnConfiguring(DbContextOptionsBuilder 
                                            optionsBuilder)        
        {
            optionsBuilder.UseSqlServer("yoursConnectionString");        
        }    
    }
}

And I’ve inserted in database 6828 rows for Users table.

Next step — get data from DB without AsNoTracking and with AsNoTracking and compare performance. For comparing I use Benchmark.

using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Microsoft.EntityFrameworkCore;

namespace AsNoTrackinsExample
{
    class Program    
    {
        static void Main(string[] args)        
        {
            var summary = BenchmarkRunner.Run<MemoryBenchmarkerDemo>();        
        }    
    }    
    
    [MemoryDiagnoser]
    public class MemoryBenchmarkerDemo    
    {        
        [Benchmark]
        public List<User> GetUsers()        
        {
            using (AppDbContext db = new AppDbContext())            
            {
                return db.Users.ToList();            
            }        
        }        
        
        [Benchmark]
        public List<User> GetUsersWithNoTracking()        
        {
            using (AppDbContext db = new AppDbContext())            
            {
                return db.Users.AsNoTracking().ToList();            
            }        
        }    
    }
}


Benchmark result


Wow! We can see an advantage in both speed of execution and memory usage. Mostly the differences will be noticeable on large amounts of data.

But remember, that we can not update any item or collection that we received with AsNoTracking, because Entity Framework does not store these objects in cache.

using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace AsNoTrackinsExample
{
    class Program    
    {
        static void Main(string[] args)        
        {
            using (AppDbContext db = new AppDbContext())            
            {
                var user = db.Users.AsNoTracking().FirstOrDefault();
                user.Age = 22;
                db.SaveChanges(); // Age will not be updated             
            }        
        }    
    }
 }

In addition to using the AsNoTrackingmethod, you can disable tracking in general for the context object.

To do this, set the false value for the db.ChangeTracker.AutoDetectChangesEnabled property:

using Microsoft.EntityFrameworkCore;

namespace AsNoTrackinsExample
{
    class Program    
    {
        static void Main(string[] args)        
        {
            using (AppDbContext db = new AppDbContext())            
            {
                db.ChangeTracker.AutoDetectChangesEnabled = false;                
                ...            
            }        
        }    
    }
}

In general, through the ChangeTrackerproperty, we can manage the tracking of an object and receive a variety of information. For example, we can find out how many objects are currently being tracked:

using System.Linq;

namespace AsNoTrackinsExample
{
    class Program    
    {
        static void Main(string[] args)        
        {
            using (AppDbContext db = new AppDbContext())            
            {
                var users = db.Users.ToList();
                int count = db.ChangeTracker.Entries().Count();            
            }        
        }    
    }
}

When should you use AsNoTracking? If you just need to display data for display without the need for further updating, then this is the case when we can use AsNoTracking.



Source: Medium - Stasoz


The Tech Platform

0 comments

Recent Posts

See All
bottom of page