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.):
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:
How is this even possible?
Usermanager uses the same context, however, when create the one-to-one relationship, query on foreignkey is not executed.
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();
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