Ef Core Returns Null Relations Until Direct Access

EF Core returns null relations until direct access

The reason is explained in the Loading Related Data section of the EF Core documentation.

The first behavior is because EF Core currently does not support lazy loading, so normally you'll get null for navigation properties until you specifically load them via eager or explicit loading. However, the Eager loading section contains the following:

Tip

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

which explains why the navigation property is not null in the second case.

Now, I'm not sure which of the two behaviors do you want to fix, so will try to address both.

The first behavior can be "fixed" by using one of the currently available methods for loading related data, for instance eager loading:

var mutants = db.Mutants.Include(m => m.OriginalCode).ToList();

The second behavior is "by design" and cannot be controlled. If you want to avoid it, make sure to use fresh new DbContext instance just for executing a single query to retrieve the data needed, or use no tracking query.

Update: Starting with v2.1, EF Core supports Lazy Loading. However it's not enabled by default, so in order to utilize it one should mark all navigation properties virtual, install Microsoft.EntityFrameworkCore.Proxies and enable it via UseLazyLoadingProxies call, or utilize Lazy-loading without proxies - both explained with examples in the EF Core documentation.

Returning Null for the Related Entity

From what I can see from your example and tags (EF Core 2.1) the issue likely is that lazy loading hasn't been enabled. Check that you've added the dependency for the EF Core Proxies and added optionsBuilder.UseLazyLoadingProxies(); to the DbContext OnModelConfiguring override.

A recommendation though is not to roll your own mappers such as the static Convert method, and instead look to leverage an existing mapper like AutoMapper. A key feature of Automapper for integrating with EF is Projection (ProjectTo). This can build your DTOs/ViewModels as part of the Linq expression that is fed to the database resulting in far, far more efficient queries and no multi-hits from things like lazy loading.

With Lazy loading you will have 1 query hit to get all fields from your user, then 1 query hit to get all fields from your City, plus 1 hit for each and every other lazy-load call. If you are doing something like fetching a list of users, you would have 1 hit to get the list of users, but then 1 hit for each city for each user!

With eager loading you would have 1 query hit to get all fields from your user and their related city, which is a lower performance hit. However it is still fetching all fields, whether your DTO/ViewModel needs them or not. There is also the risk of forgetting to explicitly eager load related data in queries, especially when expanding entities to add new relationships, which ends up reverting to the lazy load performance penalties or issues.

With Automapper's ProjectTo, you would have 1 query hit to get only the fields from User, City, and any other related entities which the DTO/ViewModel requested. No need to remember to Include relatives, or worry about lazy load hits. Clean, efficient, and future proof.

One-To-Many relationship in Entity Framework: Why foreign key value is null?

You need to specify EF to include child.

var company = await _context.Company.Where(p => p.companyName == "BestCompany").Include(p=> p.PhotoCollection).FirstOrDefaultAsync();

EF7.Beta5: Hirachical navigation on answered instances returns null - direct access works

Lazy loading isn't implemented yet in EF7. If the related entities are already loaded, the navigation properties will be fixed-up. If they're not, the navigation properties will be null unless you load them. Either eagerly...

var companies = db.Companies.Include(c => c.Departments);

...or explicitly.

db.Departements.Where(d => d.CompanyId == company.Id).Load();


Related Topics



Leave a reply



Submit