Entity Framework Core

Entity Framework Core Behavior

Entity framework core by default implementation keeps track queried entity. Here is an example construct using Postgres (Npgsql).

 var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
 optionsBuilder.UseNpgsql(configuration.GetConnectionString("Default"));
 var dbContext = new ApplicationDbContext(optionsBuilder.Options);

If you want to set default to false, do it like this

 var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
 optionsBuilder.UseNpgsql(configuration.GetConnectionString("Default"))
    .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
 var dbContext = new ApplicationDbContext(optionsBuilder.Options);

And also, if you use projections, Entity Framework Core will treat the returned entity as No-Tracking. For example

 var person = await dbContext.Persons.Select(e => new Person
 {
    Id = e.Id,
    FullName = e.FullName,
    Address = e.Address
 })
 .Where(e => e.Id == dto.Id)
 .FirstOrDefaultAsync(cancellationToken);

Then if you want to track this entity, you have to use .Attach() API.

Performance Perspective

There are a couple ways to get and update data using Entity Framework Core. In this example will cover most common ways when using Entity Framework Core when dealing with get and update data

Summary

When you have an entity that has dozens of columns, and try to update just a couple of columns, get the entity using projections only for specific column that you need, check the state, if pass then proceed to update. This approach will reduce the cost for data transfer and query from database to application.

Rank 1

Code :

using var dbContext = new AppDbContext(_optionsBuilder.Options);
var person = dbContext.Person
.Select(e => new Person
{
   Id = e.Id,
   FullName = e.FullName,
   EmailAddress = e.EmailAddress
})
.First(e => e.Id == PersonId);

dbContext.Attach(person);

person.FullName = "updated";
person.EmailAddress = "test@test.com";

dbContext.SaveChanges();

Rank 2

Code :

using var dbContext = new AppDbContext(_optionsBuilder.Options);
var person = dbContext.Person
   .AsNoTracking()
   .First(e => e.Id == PersonId);

dbContext.Attach(person);

person.FullName = "updated";
person.EmailAddress = "test@test.com";

dbContext.SaveChanges();

Rank 3

Code :

using var dbContext = new AppDbContext(_optionsBuilder.Options);
var person = dbContext.Person
   .First(e => e.Id == PersonId);

person.FullName = "updated";
person.EmailAddress = "test@test.com";

dbContext.SaveChanges();