Entity Framework lazy loading with AsNoTracking()

13,228

You've specified for EF to not track your instantiated Account value:

var account = _dbcontext.Account.AsNoTracking().SingleOrDefault(m=>m.id == 1);

Thus trying to access navigation properties off of them will never work:

var contactName = account.Contact.Name

You can explicitly include navigation properties you want by using the Include(). So the following should work:

var account = _dbcontext.Account
  .Include(a => a.Contact)
  .AsNoTracking()
  .SingleOrDefault(m=>m.id == 1);

var contactName = account.Contact.Name;  // no exception, it's already loaded

I'm really not convinced that using AsNoTracking prevents from using lazy loading

It can be tested really quickly:

DotNetFiddle Full Example

public static void Main()
{
    var actor1 = new Actor { Id = 1, Name = "Vin Diesel" }; 
    var movie1 = new Movie { Id = 1, Title = "Fast and Furious", PrimaryActor = actor1 };
    using (var context = new MovieDb())
    {

        Console.WriteLine("========= Start Add: movie1 ==============");
        context.Movies.Add(movie1);
        context.SaveChanges();
        Console.WriteLine("========= END Add: movie1 ==============");

        var m1 = context.Movies.First();
        Console.WriteLine(m1.PrimaryActor.Name);

        var m2 = context.Movies.Include(m => m.PrimaryActor).AsNoTracking().First();
        Console.WriteLine(m2.PrimaryActor.Name);

        var m3 = context.Movies.AsNoTracking().First();
        Console.WriteLine(m3.PrimaryActor.Name);
    }
}

Output:

========= Start Add: movie1 ==============
========= END Add: movie1 ==============
Vin Diesel
Vin Diesel
Run-time exception (line 31): Object reference not set to an instance of an object.

The variable m1 is tracked by the context, thus it can Lazy Load the navigation property and prints the value. m2 is not tracked, but I've explicitly included the navigation property so it prints the value. m3 is not tracked and I have not included it explicitly thus the value is null and we get a NRE.

Share:
13,228

Related videos on Youtube

John
Author by

John

Updated on June 04, 2022

Comments

  • John
    John almost 2 years

    We are currently using lazy loading for Entity Framework and running into out of memory exception. The reason why we're running into this exception is because the Linq query loads a lot of data and at latter stages it's using lazy loading to load navigation properties. But because we don't use NoTrackingChanges Entity Framework cache builds up really quickly which results in out of memory error.

    My understanding with EF is the we should always use NoTrackingChanges on query unless you want to update the returned object from the query.

    I then tested using NoChangeTracking:

    var account = _dbcontext.Account
                            .AsNoTracking()
                            .SingleOrDefault(m => m.id == 1); 
    var contactName = account.Contact.Name
    

    but I get the following error:

    System.InvalidOperationException: When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects.

    • John
      John over 6 years
      @SteveGreene if i disable proxy creation then lazy loading wont work. Is that true?
    • Erik Philips
      Erik Philips over 6 years
      Don't add code or directly related comments as comments, just update your question so other users don't have to wade through comments to understand the question.
  • Douglas Gaskell
    Douglas Gaskell almost 6 years
    This really makes for a catch-22 when you need to load recursive entities as no tracking....
  • Erik Philips
    Erik Philips about 5 years
    @DouglasGaskell not at all.
  • antoninod
    antoninod almost 4 years
    @ErikPhilips Thank you for this answer. I'm really not convinced that using AsNoTracking prevents from using lazy loading, but it is not very easy to find information about that. Could you please provide references about what you are saying?
  • m12lrpv
    m12lrpv over 3 years
    Seeing the same here too. Lazy loading with AsNoTracking... you can flip a coin as to whether it will work or not. Sometimes it does, sometmes it doesn't.