如何使用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);
简短的回答:你做不到。 但是,有选择:
-
稍后明确加载关系:
await context.Entry(user).Reference(x => x.Address).LoadAsync();
这当然需要发出额外的查询,但您可以继续通过
UserManager
拉取用户。 -
只需使用上下文。 您不必使用
UserManager
。 它只是使一些事情变得更简单。 您可以随时通过上下文直接回溯查询:var user = context.Users.Include(x => x.Address).SingleOrDefaultAsync(x=> x.Id == User.Identity.GetUserId());
FWIW,您的导航属性不需要virtual
。 这是懒惰加载,EF Core目前不支持。 (虽然,EF Core 2.1,目前正在预览中,实际上会支持延迟加载。)无论如何,延迟加载通常是一个坏主意,所以你仍然应该坚持或明确地加载你的关系。