Why is my Entity relationship not resolved?

asp.net-core c# entity-framework-core npgsql

Question

Using the following entities:

User.cs:

public class User {
    [Key]
    public Guid Id { get; set; }

    public List<Session> Sessions { get; set; }
}

Session.cs:

public class Session
{
    [Key]
    public Guid Id { get; set; }

    public Guid UserId { get; set; }

    public User User { get; set; }
}

ApiContext.cs:

public class ApiContext : DbContext
{
    public ApiContext(DbContextOptions<ApiContext> options) : base(options)
    {
        Database.EnsureCreated();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Added to try to fix the issue
        modelBuilder.Entity<User>().HasMany(u => u.Sessions).WithOne(u => u.User);
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Session> Sessions { get; set; }
}

And then creating a session:

var newSession = new Session
{
    User = someUser
};

Db.Sessions.Add(newSession);

Upon getting the session:

var session = apiContext.Sessions.SingleOrDefault(s => s.id == wantedUid);

session.UserId is well set and valid, however session.User is null.

By my comprehension the context should have automatically set session.User according to session.UserId.
As noted in the code I tried to add the HasMany constraint explicitly despite the fact that it should be automatic (see docs).

Why is this happening and how can I fix it? Is the Guid ID type messing things up?

1
0
9/24/2018 6:30:24 PM

Accepted Answer

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 retry the data needed.

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.

46
7/9/2018 6:02:40 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