Search code examples
entity-frameworkasp.net-coreasp.net-identity

Property of custom IdentityUser gets populated with data fetched by an unrelated EF context query


I am trying to understand how the following is possible:

In a asp.net core 3.1 web app, I've defined a custom IdentityUser class:

public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }
    public UserSettings Settings { get; set; } = new UserSettings();
}

where UserSettings is:

public class UserSettings
{        
    public int Id { get; set; }
    public string ApiKey { get; set; }
    public string UserId { get; set; }
    public ApplicationUser User { get; set; }
}

The one-to-one relationship is defined using fluent api:

modelBuilder.Entity<UserSettings>()
    .HasOne(e => e.User)
    .WithOne(e => e.Settings)
    .HasForeignKey<UserSettings>(e => e.UserId)
    .IsRequired();            

In the controller with UserManager<ApplicationUser> userManager injected, I understand that:

var user = await userManager.GetUserAsync(User);

does not populate the Settings property with data from the data store. (I wonder why, though, because it does fetch data for the Name property.):

enter image description here

But if I fetch Settings data using the ApplicationDbContext directly:

var user = await userManager.GetUserAsync(User);
var settings = _applicationDbContext.UserSettings.SingleOrDefault(s => s.UserId == user.Id);

the user.Settings property gets populated:

enter image description here

How is this even possible?


Solution

  • Usermanager uses the same context, however, when create the one-to-one relationship, query on foreignkey is not executed.

    enter image description here

    You need to eager loading the record so that the settings is fetched.

    var user = await _userManager.GetUserAsync(User);
    var temp = await _dbContext.Users
            .Include(S => S.Settings)
            .AsSplitQuery()
            .IgnoreAutoIncludes()
            .ToListAsync();
    

    enter image description here

    enter image description here

    That’s why you can fetch the data through using the ApplicationDbContext directly. Data is not separated, but not loaded.

    Here is the document https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager