1

I am working on asp.net MVC 5 application. I am using Identity for creating users. I am using it first time and creating first mvc 5 application. I have two types of users. I want two tables for both types of users. So first record should be inserted in aspnetuser table and then in related tables and aspnetuser table should be linked with both tables so that i can access them. I have created models for both types of users. How can i link them with identity in model ?

Please suggest

1 Answer 1

5

Well, first, you can only truly have one user, at least in terms of the stuff Identity does. You can subclass that single user to create other types, though. So, essentially, you'd have a setup like:

public class ApplicationUser : IdentityUser
{
    ...
}

public class FooUser : ApplicationUser
{
    ...
}

public class BarUser : ApplicationUser
{
    ...
}

public class BazUser : ApplicationUser
{
    ...
}

In other words, just one class inherits directly from IdentityUser, while all your various types will inherit from that one class (in this case, ApplicationUser).

By default, Entity Framework handles inheritance via STI or Single Table Inheritance. How this works is that you'll have just one table AspNetUsers (the default table name for the Identity user), and any properties your subclasses add will be added as columns on that table. This means that all your subclass properties have to be nullable, since if a different subclass or just the base ApplicationUser class are persisted that property wouldn't be set.

If that's not acceptable, there's other inheritance strategies you can implement, namely TPT (Table-Per-Type) and TPC (Table-Per-Concrete Type). In TPT, the base, shared properties go all in one table and then each subtype has its own table with just columns for the properties it adds. In TPC, every class gets it's own table for everything, so each of your individual subtypes would have all of the Identity columns added. I don't believe this particular option would be compatible with Identity, though, or at the very least it would be highly burdensome as all the foreign key relationships between things like roles and claims would have to be duplicated for each table. Even if you could hack Identity to make that work, you'd lose any cohesive way of doing anything with all users, regardless of type, at once.

Basically, your options are the default, also known as TPH (Table-Per-Hierarchy), or TPT. However, TPT is less efficient because it essentially requires a join for every query just to get the full instance. If you absolutely need to have non-nullable properties on your subclass, it might be an appropriate option. However, remember that the property only needs to be nullable at the database-level. If you go with TPH, you can still require that those properties have values via validation in the application.

Sign up to request clarification or add additional context in comments.

10 Comments

In this scene, is the could you please clarify me if the following approach is true or not? Assume that I have a form (Create) for creating different type of users: FooUser, BarUser, BazUser and there is a Type dropdownlist on the Create form in order to determine the user types. In order to make user operations, I should create a ViewModel containing all of three models. During create process, I fill this viewmodel according to the user type and pass it to the Controller. >>>
>>> Then I will check the user type parameter and create an instance according to the user type (FooUser, BarUser, BazUser). Then fill this new model with the parameters coming from Create page and then pass it to the ASP.NET Identity's UserManager.Create() method. Is this approach fully true? Or is there a better approach for creating a new user with this scenario you mentioned in your answer? Thanks in advance...
Like I said in a comment on another post, the UserManager instance in the scaffolded AccountController is an instance of UserManager<ApplicationUser>. If you use that, all "user" subclasses will be downcast to ApplicationUser. You would need an instance of UserManager<FooUser>, UserManager<BarUser>, etc. to save the right types. Other than that, your approach seems fine.
There is a problem when retrieving properties of subclasses (FooUser, BarUser, BazUser) bu using ASP.NET Identity UserManager. Could you also post how to reach these custom properties and retrieve data from AspNetUsers table? Thanks...
Again, you need class-specific instances of UserManager<TUser>. If you use the UserManager property in AccountController by default, that is actually an instance of UserManager<ApplicationUser>. To work with FooUser, for example, you need an instace of UserManager<FooUser>.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.