如何使用UserManager在IdentityUser上加载导航属性

我已经扩展了IdentityUser以包含用户地址的导航属性,但是当使用UserManager.FindByEmailAsync获取用户时,不会填充导航属性。 ASP.NET Identity Core是否有某种方法可以填充Entity Framework的Include()等导航属性,还是必须手动执行?

我已经设置了这样的导航属性:

 public class MyUser : IdentityUser { public int? AddressId { get; set; } [ForeignKey(nameof(AddressId))] public virtual Address Address { get; set; } } public class Address { [Key] public int Id { get; set; } public string Street { get; set; } public string Town { get; set; } public string Country { get; set; } } 

不幸的是,您必须手动执行此操作或创建自己的IUserStore ,其中您在FindByEmailAsync方法中加载相关数据:

 public class MyStore : IUserStore, // the rest of the interfaces { // ... implement the dozens of methods public async Task FindByEmailAsync(string normalizedEmail, CancellationToken token) { return await context.Users .Include(x => x.Address) .SingleAsync(x => x.Email == normalizedEmail); } } 

当然,为此实施整个商店并不是最好的选择。

您也可以直接查询商店:

 UserManager userManager; // DI injected var user = await userManager.Users .Include(x => x.Address) .SingleAsync(x => x.NormalizedEmail == email); 

简短的回答:你做不到。 但是,有选择:

  1. 稍后明确加载关系:

     await context.Entry(user).Reference(x => x.Address).LoadAsync(); 

    这当然需要发出额外的查询,但您可以继续通过UserManager拉取用户。

  2. 只需使用上下文。 您不必使用UserManager 。 它只是使一些事情变得更简单。 您可以随时通过上下文直接回溯查询:

     var user = context.Users.Include(x => x.Address).SingleOrDefaultAsync(x=> x.Id == User.Identity.GetUserId()); 

FWIW,您的导航属性不需要virtual 。 这是懒惰加载,EF Core目前不支持。 (虽然,EF Core 2.1,目前正在预览中,实际上会支持延迟加载。)无论如何,延迟加载通常是一个坏主意,所以你仍然应该坚持或明确地加载你的关系。