【问题标题】:Accessing Navigation Properties from IdentityUser when LazyLoading is off当 LazyLoading 关闭时从 IdentityUser 访问导航属性
【发布时间】:2016-03-18 00:17:05
【问题描述】:

我使用代码优先模型进行了此设置:

public class TestContext :IdentityDbContext<TestUser>
{
    public TestContext()
        : base("TestConnection")
    {         
        this.Configuration.LazyLoadingEnabled = false;

    }

    public DbSet<Customer> Customers{get;set;}

}

public class TestUser : IdentityUser
{
    public virtual Customer Customer { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName {get; set;}
}

我已扩展 IdentityUser 以包含“客户”类的实例。

现在考虑这段代码:

var user = UserManager.FindById("some id");                  
if (user != null)
{       
    string str=user.Customer.FirstName; //since lazy loading is off, user.Customer is null and hence gives null reference exception.
}

由于延迟加载已关闭,user.Customer 为 null,因此会给出 null 引用异常。 如果有人可以在 LazyLoading 关闭时帮助我访问 IdentityUser 的导航属性,我会很高兴。

谢谢。

【问题讨论】:

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


【解决方案1】:

如果您总是想在不使用延迟加载的情况下加载相关数据,那么您需要编写自己的 UserStore 实现并将其插入您的 UserManager。比如……

public class ApplicationUserStore : UserStore<TestUser>
{
    public ApplicationUserStore(TestContext context) : base(context)
    {
    }

    public override TestUser FindByIdAsync(string userId)
    {
        return Users.Include(c => c.Customer).FirstOrDefault(u => u.Id == userId);
        //you may want to chain in some other .Include()s like Roles, Claims, Logins etc..
    }
}

然后,当您创建 UserManager 时,插入 UserStore 的此实现,您的 Customer 数据将与用户一起加载。这可能看起来像......

public class TestUserManager : UserManager<TestUser>
{
    public TestUserManager() : base(new ApplicationUserStore(new TestContext()))
    {
    }

}

根据您的项目,UserManager 的实现会有所不同。

【讨论】:

  • 您先生拯救了我的一天。我意识到急切加载不适用于 IdentityDbContext,所以这是解决方法。
【解决方案2】:

我已经解决了这个问题:

创建自定义 UserManager

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationUser> passwordHasher, IEnumerable<IUserValidator<ApplicationUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationUser>> logger, IHttpContextAccessor contextAccessor) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger, contextAccessor) { }

    public override Task<ApplicationUser> FindByIdAsync(string userId)
    {
        return Users.Include(c => c.Esercizio).FirstOrDefaultAsync(u => u.Id == userId);
    }
}

替换默认的 UserManager 服务

在您的 ConfigureServices 中添加:

services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders().AddUserManager<ApplicationUserManager>();

更改 DI 的参数

来自

[FromServices]UserManager<ApplicationUser> userManager

[FromServices]ApplicationUserManager userManager

希望对你有帮助

【讨论】:

  • 一百万次感谢您!我几乎放弃了这种方式,并打算进行另一个数据库调用来提取必要的对象,因为我能找到的所有解决方案都涉及覆盖几乎整个框架!
猜你喜欢
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
相关资源
最近更新 更多