How to use Lazy Loading for DbQuery in EF Core?

c# ef-core-2.2 entity-framework-core

Question

I am using Lazy Loading for EF Core 2.2.3 with proxies which works well with DbSets. Now I have to load data from a SQL View and am using DbQuery for this. When trying to load related data for the entity used in the query, I'm getting a DetachedLazyLoadingWarning:

Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.DetachedLazyLoadingWarning: An attempt was made to lazy-load navigation property 'ProjectStatus' on detached entity of type 'ProjectProxy'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking()'.'. This exception can be suppressed or logged by passing event ID 'CoreEventId.DetachedLazyLoadingWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.

I don't use AsNoTracking() anywhere in my code.

The DbQuery is defined in OnModelCreating of the context. Excerpt:

 modelBuilder.Query<ProjectView>()
                .ToQuery(() => Projects
                .Select(p => new ProjectView()
                {
                    Id = p.Id,
                    ProjectCategory = p.ProjectCategory,
                    ProjectPhase = p.ProjectStatus.ProjectPhase,
                }));

Projects is a DbSet of the context. Project.ProjectCategory is a notMapped-Readonly-Property that uses the relation Project.ProjectStatus.

The Properties of the context:

public virtual DbSet<Project> Projects { get; set; }
public virtual DbSet<ProjectStatus> ProjectStatus { get; set; }
public virtual DbQuery<ProjectView> ProjectViews { get; set; }

Excerpt of the classes:

    public partial class Project
    {
            [NotMapped]
            public string ProjectCategory
            {
                get
                {
                    if (this.ProjectStatus == null)
                        return string.Empty;
                    var foo = "someweiredcalculations";

                    return foo
                }
            }
            public virtual ProjectStatus ProjectStatus { get; set; }
            public int ProjectStatusId { get; set; }
            public int Id { get; set; }

}

public class ProjectView
{
        public int Id { get; set; }
        public string ProjectCategory { get; set; }
        public string ProjectPhase { get; set; }
}

public partial class ProjectStatus : BaseEntity, IIdEntity<int>
    {

        public int Id { get; set; }
        public string ProjectPhase { get; set; }
        public virtual ICollection<Project> Projects { get; set; } = new HashSet<Project>();

    }

How can I make Lazy Loading work for this DbQuery?

Thank you very much.

1
1
4/17/2019 5:10:48 PM

Popular Answer

This seems to be by design, regardless whether .AsNoTracking() is used or not. I did not find any documentation on this.

If you are stuck on .net core 2 the only workaround I found was to load related entities in a separate query. Effectively breaking lazy loading.

As of .net core 3+ it is possible to work around this by eager loading related properties (.Include(x => x.ProjectStatus)) when Lazy Loading is Used. This was fixed by: https://github.com/aspnet/EntityFrameworkCore/issues/12780. And the error message when using lazy loading was changed to: 'Unable to track an instance of type 'FooQuery' because it does not have a primary key. Only entity types with primary keys may be tracked.'

0
11/22/2019 5:27:33 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow