The only context instances I use QueryTrackingBehavior.NoTracking are Reporting contexts, not API contexts unless the API applicable to that context is entirely read-only.
NoTracking will provide a nominal speed boost for data Read operations.
You can use NoTracking for update operations, but you will require a bit of additional code, and incur a nominal penalty for Updates. If you are building an Append-only (Inserts, no Updates) then NoTracking provides no penalty.
Why: When EF loads an entity with tracking, 2 things happen. First, the reference is loaded into the local cache. Second, a proxy is used which keeps track of updates against fields on the entity.
Given an update accepting a new Message for a Record entity:
void UpdateMessage(int recordId, string message);
With tracking:
void UpdateMessage(int recordId, string message)
{
using(var context = new AppContext())
{
var record = context.Records.Single(x => x.RecordId == recordId);
record.Message = message;
context.SaveChanges();
}
}
Without tracking:
void UpdateMessage(int recordId, string message)
{
using(var context = new AppContext())
{
var record = context.Records.AsNoTracking().Single(x => x.RecordId == recordId);
record.Message = message;
context.Update(record); // or Attach() and set Modified state.
context.SaveChanges();
}
}
These look very similar on the surface, but there is a distinct difference that will happen under the hood:
In the first case, EF will generate an SQL statement similar to:
UPDATE tblRecords SET Message = @1 WHERE RecordId = @0
In the second case, EF will generate:
UPDATE tblRecords SET Message = @1, SomeField = @2, SomeOtherField = @3, CreatedAt = @4, CreatedBy = @5 WHERE RecordId = @0
When taking untracked entities and "Updating" them, EF has no idea what changed, so every column is updated. With tracking, only fields that were updated will be in the query. For larger entities this can be noticeable.
Inserts, including for append-only systems aren't affected since these would include all columns anyways.