具有asp网络标识的自定义实体(一对多)

时间:2014-10-30 07:03:40

标签: 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().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; }
}

1 个答案:

答案 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);
}