【问题标题】:Custom entities with asp net identity (one-to-many)具有 asp 网络标识的自定义实体(一对多)
【发布时间】:2014-10-30 07:03:40
【问题描述】:

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

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 实体为空。

但是,使用它来加载用户并填充所有实体。我在这里所做的只是访问实体,但不对它们做任何事情。

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;
    }

那么为什么实体在延迟加载的情况下为空,但如果我只是在上下文中访问它们而不对它们做任何事情,它们就可以工作?

我使用的是 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; }
}

【问题讨论】:

    标签: c# entity-framework asp.net-identity


    【解决方案1】:

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

    关闭延迟加载,并在数据库中查询地址类型和国家/地区,然后将其拉入 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)
        }
    }
    

    然后在你的 UserManager 中使用这个新的 Store

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

    【讨论】:

    • 我对实体框架延迟加载的理解已经关闭。我认为即使没有获取它们相关的内容,它们也会被加载到上下文中。感谢您清除它。
    猜你喜欢
    • 2015-06-16
    • 2013-04-07
    • 2020-08-05
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2017-07-25
    相关资源
    最近更新 更多