330

I have a question regarding the .AsNoTracking() extension, as this is all quite new and quite confusing.

I'm using a per-request context for a website.

A lot of my entities don't change so don't need to be tracked, but I have the following scenario where I'm unsure of what's going to the database, or even whether it makes a difference in this case.

This example is what I'm currently doing:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

This is the same as above but removing the .AsNoTracking() from Step 1:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

The Steps 1 & 2 use the same context but occur at different times. What I can't work out is whether there is any difference. As Step 2 is an update I'm guessing both will hit the database twice anyway.

Can anyone tell me what the difference is?

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
dotnetnoob
  • 10,783
  • 20
  • 57
  • 103

6 Answers6

258

The difference is that in the first case the retrieved user is not tracked by the context so when you are going to save the user back to database you must attach it and set correctly state of the user so that EF knows that it should update existing user instead of inserting a new one. In the second case you don't need to do that if you load and save the user with the same context instance because the tracking mechanism handles that for you.

Jess
  • 23,901
  • 21
  • 124
  • 145
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 3
    Can we get the same benefits for anonymous classes in select query, such as context.Users.Select(u=> new { Name = u.Name })? Thanks. – Dilhan Jayathilake Feb 06 '17 at 23:33
  • 7
    @DilhanJayathilake: Anonymous classes don't represent the entity itself so they don't have tracking. – Ladislav Mrnka Feb 13 '17 at 13:42
  • 1
    Since EF6 infers the entity key incorrectly on a View sometimes, does AsNoTracking() ignore the key and therefore be an alternative to manually fixing the key (assuming other benefits of the key are not needed). – crokusek Nov 07 '17 at 22:51
  • 4
    Also note, the biggest effect AsNoTracking has is that lazy loading will not work – Douglas Gaskell May 23 '18 at 20:05
  • @LadislavMrnka isn't quite correct. If your anonymous type includes instances of Entities that can be tracked, EF will track the entities within the anonymous type. So AsNoTracking() can be applicable for an anonymous type. – Mick May 12 '22 at 07:55
238

see this page Entity Framework and AsNoTracking

What AsNoTracking Does

Entity Framework exposes a number of performance tuning options to help you optimise the performance of your applications. One of these tuning options is .AsNoTracking(). This optimisation allows you to tell Entity Framework not to track the results of a query. This means that Entity Framework performs no additional processing or storage of the entities which are returned by the query. However, it also means that you can't update these entities without reattaching them to the tracking graph.

there are significant performance gains to be had by using AsNoTracking

Moji
  • 5,720
  • 2
  • 38
  • 39
  • 21
    It seems that the gains may be counterbalanced sometimes: http://stackoverflow.com/questions/9259480/entity-framework-mergeoption-notracking-bad-performance – Fabrice Dec 28 '16 at 00:49
  • 6
    My performance gain with a complex query loading a parent child relationship with include in one step was about 50% – Karl Jan 19 '18 at 06:33
  • 1
    Another feedback from 2022: there was a *huge* gain using AsNoTracking() (Entity Framework 6). Actually for other reasons - not exposing the details here, but it's related to the Include() method of EF - I have disabled tracking instead of using AsNoTracking() for the DbContext I'm using regarding the specific linq queries I'm doing in my case: ctx.Configuration.AutoDetectChangesEnabled = false;). I would say the performance gain was at least 95%, probably more (I'm not overestimating: execution time went down from more than 1 hour to less than 15 sec...) – ggo Jul 25 '22 at 16:41
73

No Tracking LINQ to Entities queries

Usage of AsNoTracking() is recommended when your query is meant for read operations. In these scenarios, you get back your entities but they are not tracked by your context.This ensures minimal memory usage and optimal performance

Pros

  1. Improved performance over regular LINQ queries.
  2. Fully materialized objects.
  3. Simplest to write with syntax built into the programming language.

Cons

  1. Not suitable for CUD operations.
  2. Certain technical restrictions, such as: Patterns using DefaultIfEmpty for OUTER JOIN queries result in more complex queries than simple OUTER JOIN statements in Entity SQL.
  3. You still can’t use LIKE with general pattern matching.

More info available here:

Performance considerations for Entity Framework

Entity Framework and NoTracking

Bernard Vander Beken
  • 4,848
  • 5
  • 54
  • 76
NullReference
  • 2,828
  • 2
  • 30
  • 33
  • 1
    "You still can’t use LIKE with general pattern matching" - I can't find any official reference for this and it does seem to work fine for me – kofifus Sep 03 '21 at 07:37
46

Disabling tracking will also cause your result sets to be streamed into memory. This is more efficient when you're working with large sets of data and don't need the entire set of data all at once.

References:

Community
  • 1
  • 1
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346
23

AsNoTracking() allows the "unique key per record" requirement in EF to be bypassed (not mentioned explicitly by other answers).

This is extremely helpful when reading a View that does not support a unique key because perhaps some fields are nullable or the nature of the view is not logically indexable.

For these cases the "key" can be set to any non-nullable column but then AsNoTracking() must be used with every query else records (duplicate by key) will be skipped.

crokusek
  • 5,345
  • 3
  • 43
  • 61
  • 6
    Just to reiterate the importance of this with Views, I have a query from a view which returns 7 unique records when run via SSMS. When run via EF, without the AsNoTracking modifier, I get the first record, three copies of the second and three copies of the third. This took a lot of incredulous head-scratching to fix, and it was using AsNoTracking which fixed it! – Ade Mar 22 '18 at 14:26
  • I had this exact same issue when using Linq to Entities while querying a View with no primary keys. Only found out about AsNoTracking after half a day of head-scratching. This ASP.Net forum post eventually led me to it. https://forums.asp.net/t/1864180.aspx?EF+returning+two+identical+records+when+2+different+records+are+in+the+table+ – red_dorian Sep 14 '18 at 15:35
16

If you have something else altering the DB (say another process) and need to ensure you see these changes, use AsNoTracking(), otherwise EF may give you the last copy that your context had instead, hence it being good to usually use a new context every query:

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
andrew pate
  • 3,833
  • 36
  • 28