使用用户管理器加载用户时
private UserManager<MyUser> GetUserManager()
{
var userStore = new UserStore<MyUser>(_context);
return new UserManager<MyUser>(userStore);
}
public MyUser GetUser(string username)
{
return GetUserManager().FindByName(username);
}
我的UserAddress实体已填充,但UserAddress中的AddressType和Country实体为null。
但是使用它来加载用户并填充所有实体。我在这里所做的只是访问实体,但不对它们做任何事情。
public MyUser GetUser(string username)
{
var addressTypes = _context.AddressType.ToList();
var countries = _context.Countries.ToList();
return GetUserManager().FindByName(username);
}
同样启用延迟加载的工作方式如下所示。
public MyUser GetUser(string username)
{
_context.Configuration.LazyLoadingEnabled = true;
var user = GetUserManager().FindByName(username);
_context.Configuration.LazyLoadingEnabled = false;
return user;
}
那么为什么实体在延迟加载时为null,但如果我只是在上下文中访问它们但对它们什么也不做呢?它们可以工作吗?
我正在使用DB First。继承我的实体(重要的位)
public class MyUser : IdentityUser
{
public MyUser()
{
this.Address = new List<UserAddress>();
}
public virtual IList<UserAddress> Address { get; set; }
}
[Table("AddressTypes")]
public partial class AddressTypes
{
public AddressTypes()
{
this.Address = new List<UserAddress>();
}
public int Id { get; set; }
public virtual IList<UserAddress> Address { get; set; }
}
[Table("Country")]
public partial class Country
{
public Country()
{
this.Address = new List<UserAddress>();
}
public int Id { get; set; }
public virtual IList<UserAddress> Address { get; set; }
}
[Table("UserAddress")]
public partial class UserAddress
{
public int Id { get; set; }
public string UserId { get; set; }
public int AddressTypeId { get; set; }
public int CountryId { get; set; }
public AddressTypes AddressType { get; set; }
public Country Country { get; set; }
[ForeignKey("UserId")]
public MyUser User { get; set; }
}
答案 0 :(得分:3)
您已经在这里回答了自己的问题。
使用延迟加载,当您使用点表示法访问数据库时,将重新查询数据库以获取所请求的信息。因此,在您的示例中,访问user.AddressType
实际上会向DB发出另一个请求,以获取与该用户关联的AddressType并将其存储在Context中。
关闭Lazy Loading,并查询数据库中的AddressTypes和Countries,然后将其拉入DbContext,这样当您访问相关信息,即user.AddressType
时,该用户的AddressType已经加载到DbContext,所以它将使用它,而不必重新查询数据库。如果没有预取它们,它们将始终为空。
如果您始终想要引入这些相关表格,则需要修改查询以使用.Include()
方法。为此,您需要从UserStore派生并覆盖FindByName方法,如此。
public class MyUserStore : UserStore<MyUser>
{
public MyUserStore(DbContext context) : base(context)
{
}
public override MyUser FindByName(string userName)
{
return Users.Include(x=>x.AddressType).Include(x=>x.Country).FirstOrDefault(n=>n.UserName == userName);
//you may need to also include the following includes if you need them
//.Include(x=>x.Roles).Include(x=>x.Claims).Include(x=>x.Logins)
}
}
然后在UserManager中使用此新商店
private MyUserManager GetUserManager()
{
var userStore = new MyUserStore(_context);
return new UserManager<MyUser>(userStore);
}