C# 具有asp net标识的自定义实体(一对多)

C# 具有asp net标识的自定义实体(一对多),c#,entity-framework,asp.net-identity,C#,Entity Framework,Asp.net Identity,当我使用用户管理器加载用户时 private UserManager<MyUser> GetUserManager() { var userStore = new UserStore<MyUser>(_context); return new UserManager<MyUser>(userStore); } public MyUser GetUser(string username) { return GetUserManager(

当我使用用户管理器加载用户时

private UserManager<MyUser> GetUserManager()
{
    var userStore = new UserStore<MyUser>(_context);
    return new UserManager<MyUser>(userStore);
}

public MyUser GetUser(string username)
{
    return GetUserManager().FindByName(username);
}
另外,启用延迟加载的工作方式如下所示

    public MyUser GetUser(string username)
    {
        _context.Configuration.LazyLoadingEnabled = true;
        var user = GetUserManager().FindByName(username);
        _context.Configuration.LazyLoadingEnabled = false;
        return user;
    }
那么,为什么延迟加载时实体为空,但如果我只是在上下文中访问它们,而不对它们进行任何操作,它们就可以工作呢

我先用DB。这里是我的实体(重要的部分)

公共类MyUser:IdentityUser
{
公共MyUser()
{
this.Address=新列表();
}
公共虚拟IList地址{get;set;}
}
[表(“地址类型”)]
公共部分类地址类型
{
公共地址类型()
{
this.Address=新列表();
}
公共int Id{get;set;}
公共虚拟IList地址{get;set;}
}
[表(“国家”)]
公共部分阶级国家
{
公共国家()
{
this.Address=新列表();
}
公共int Id{get;set;}
公共虚拟IList地址{get;set;}
}
[表(“用户地址”)]
公共部分类用户地址
{
公共int Id{get;set;}
公共字符串用户标识{get;set;}
public int AddressTypeId{get;set;}
public int CountryId{get;set;}
公共地址类型地址类型{get;set;}
公共国家{get;set;}
[外键(“用户ID”)]
公共MyUser用户{get;set;}
}

您已经回答了自己的问题。 通过延迟加载,当您使用点表示法访问数据库时,将重新查询数据库以获取请求的信息。因此,在您的示例中,访问
user.AddressType
实际上会向DB发出另一个请求,以获取与该用户关联的AddressType并将其存储在上下文中

禁用延迟加载,并查询数据库中的地址类型和国家/地区,然后将其拉入DbContext,因此当您访问相关信息(即
user.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)
    }
}
公共类MyUserStore:UserStore { 公共MyUserStore(DbContext上下文):基(上下文) { } 公共覆盖MyUser FindByName(字符串用户名) { 返回Users.Include(x=>x.AddressType).Include(x=>x.Country).FirstOrDefault(n=>n.UserName==UserName); //如果需要,您可能还需要包括以下内容 //.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);
}
private MyUserManager GetUserManager()
{
var userStore=新的MyUserStore(_上下文);
返回新的UserManager(userStore);
}

我对实体框架延迟加载的理解是如何实现的。我认为它们会被加载到上下文中,即使不获取它们,因为它们是相关的。谢谢你澄清这一点。
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)
    }
}
private MyUserManager GetUserManager()
{
    var userStore = new MyUserStore(_context);
    return new UserManager<MyUser>(userStore);
}