6

I've this setup with code first model:

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

I've extended the IdentityUser to contain an instance of "Customer" Class.

Now consider this code:

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

since lazy loading is off, user.Customer is null and hence gives null reference exception. I'll be glad if anyone can help me in accessing the Navigation Properties of IdentityUser when LazyLoading is off.

Thanks.

Amit Mittal
  • 1,129
  • 11
  • 30
  • Is configuration done for relation between TestUser and Customer? – jd4u Oct 13 '14 at 13:37
  • Do we need any special configuration for this relation? I am sorry but I am not aware of any, please enlighten me. – Amit Mittal Oct 14 '14 at 02:32
  • Review two things: 1. OnModelCreating method of DbContext & 2. LazyLoadingEnabled : http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application – jd4u Oct 14 '14 at 11:39

2 Answers2

9

If you are always wanting to load the related data without using Lazy Loading then you will need to write your own implementation of the UserStore and plug that into your UserManager. For example..

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

then when you create your UserManager, plugin this implementation of the UserStore, and your Customer data will be loaded with the user.. this may look something like..

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

}

depending on your project, the UserManager implementation will be different.

Excommunicated
  • 1,252
  • 8
  • 14
  • 1
    You sir have saved my day. I realized that eager loading doesn't work with an IdentityDbContext so this is the workaround. – hbulens Sep 08 '15 at 13:44
4

I have solved with this:

Create a custom 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);
    }
}

Replace default UserManager service

In your ConfigureServices add this:

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

Change arguments for DI

from

[FromServices]UserManager<ApplicationUser> userManager

to

[FromServices]ApplicationUserManager userManager

I hope this helps

gidanmx2
  • 469
  • 1
  • 9
  • 24
  • Thank you times a million! I had all but given up on this way of doing it and was going to do another database call to pull the necessary object, as all solutions I could find were involving overriding almost the whole framework! – Bron Thulke Oct 25 '17 at 07:39