2

I use ASP.NET Identity 2.0 in an MVC application and there is a default table called AspNetUsers in order to keep user data with the columns below:

AspNetUsers:

Id
Email
EmailConfirmed
PasswordHash
... etc

I know that I can add custom properties to this Entity as Name, Surname, etc. to this AspNetUsers table. However, there are 2 types of users in my project: Student and Professor. Therefore I need to use different properties as shown below:

Student:

Id
Name
Surname
Email
StudentNumber
Department

Professor:

Id
Name
Email
Surname
Profession
RoomNumber

At this point I have a problem when combining these entities and I do not know how to combine them. Students and Professors are stored in AspNetUsers table and I think there is no need to define the same data as Email on different tables and it is better to use only the different properties in the Student and Professor tables as StudentNumber, RoomNumber, etc. When a user login to the system I think to use AspNetUsers table first and then get the detail data for the current user from the Student or Professor table. Is there a better approach for this situation? I think ASP.NET Identity is commonly used and many people need to store different detail properties for different type of users. Any help would be appreciated.

Jack
  • 1
  • 21
  • 118
  • 236
  • What's wrong with the approach you describe? I do it myself and it works great – Leandro Soares Jun 23 '16 at 10:25
  • I just wanted to be sure if there is a better approach and if this approach are good. If you have idea, could you please have a look at 3 questions below and comment your opinion? Thanks. – Jack Jun 23 '16 at 11:02

2 Answers2

3

Here is another possible solution, though it is up to you to determine if it is a good fit for your needs. You can you Table per Hierarchy (TPH) for your model. First make your user class abstract and put all common properties in there:

public abstract class ApplicationUser : IdentityUser
{
    //snip

    //Common properties
    public string Name { get; set; }
    public string Surname { get; set; }
}

Now create your different user type classes and inherit from the base class:

public class StudentUser : ApplicationUser
{
    public string StudentNumber { get; set; }
}

public class ProfessorUser : ApplicationUser
{
    public string Profession { get; set; }
}
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • Actually it seems to be very good approach but, as I use EF Code First, I am not sure how can I use it. For example, when I create a Student record using StudentUser entity and add Name, SUrname, will EF add the Name, Surname to the ApplicationUser table as it add StudentNumber to StudentUser? Any idea? – Jack Jun 23 '16 at 11:27
  • Yes, all properties will be in the same user table, including a column called `Discriminator` that will have a value such as `StudentUser` in it for EF to determine the type. – DavidG Jun 23 '16 at 11:31
  • Also, this is code only so is, by definition, code-first. – DavidG Jun 23 '16 at 11:35
  • I will try it asap and inform you if it works. Voted+ – Jack Jun 23 '16 at 12:00
  • I prefer this approach +1 – ediblecode Jun 23 '16 at 13:15
  • @DavidG I think I do not have to create any **Primary / Foreign Key** relationships neither between `IdentityUser` and `ApplicationUser` nor `ApplicationUser` and `StudentUser` / `ProfessorUser`. For this reason there is no **Id** property in `ApplicationUser`, `StudentUser` and `ProfessorUser`. Is **all of that** true? – Jack Jun 26 '16 at 12:11
  • @DavidG What about the id field of ApplicationUser? Shall I add id field to that class? If so what if I want to use int instead of GUID (string) data type? – Jack Jul 30 '16 at 21:28
  • @binary The id property would be part of `ApplicationUser` as normal. If you want it to be `int` then you need to follow something like this http://stackoverflow.com/questions/22547712/identity-change-guid-to-int – DavidG Jul 30 '16 at 21:45
  • @DavidG After convertig the Id properties from GUID (string) to int in ASP.NET Identiy, I tried to apply this approach and encounter some errors. I also look at [Implementing Inheritance with the Entity Framework 6 in an ASP.NET MVC 5 Application (11 of 12)](http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application) page but there is a little problem. Could you please clarify me about the issue below? Thanks... – Jack Aug 22 '16 at 17:43
  • @DavidG **1)** Is ApplicationUser abstract class of ApplicationUser class in Asp.Net Identity? **2)** I want to keep the common properties in **AspNetUsers** table in ASP.NET Identity. In that case, I think there is no need to create a class called "Person" as on that example given above and instead of that, I will use ApplicationUser class. Is that true? If so, there are some errors indicating that "... there is already a class called ApplicationUser...". Is that normal? – Jack Aug 22 '16 at 17:48
  • `ApplicationUser` inherits from `IdentityUser<>`, it is not abstract. If you want to keep the relevant properties in the right class (i.e. `StudentNumber` is *only* in the `Student` class) then you need to create the relevant sub classes. – DavidG Aug 22 '16 at 17:56
  • @DavidG Do I have to make ApplicationUser class as abstract or keep it as it was before? As far as I see the only difference is that; if I do not make it as abstract, I can also create an instance of ApplicationUser as StudentUser or ProfessorUser. It means that I can also create a user who is neither Student nor Professor and the Discriminator for this user will be ApplicationUser in the database. Is that all true? – Jack Aug 22 '16 at 21:11
  • Firstly, some places in the world are on a different timezone than you (so I was at home and then in bed.) Secondly, did you even try it out yet? You could easily answer this question on your own. – DavidG Aug 23 '16 at 09:16
  • @DavidG Thanks a lot. I tried and it behaves as I said. But I just wanted to be sure that if I should type it as abstract or not. For this reason I just want to get your valuable opinion and I would be happy if you post the last comment :) Regards... – Jack Aug 23 '16 at 17:29
  • Well I would make `ApplicationUser` abstract, as like you say, it prevents you creating a user that is neither professor or student. – DavidG Aug 23 '16 at 17:32
  • You are right, that is what I missed when asking you the last questions regarding to abstract. Many thanks again... – Jack Aug 23 '16 at 18:57
2

Move the common properties to AspNetUsers table, i.e. your name, email, surname. In the same way the login details functionality will be the same for students and teachers alike, so are these tables. For the information that is specific to a teacher or professor that's where you need your specific tables. E.g.

public class AspNetUser
{ 
    // Normal properties

    public virtual Professor Professor { get; set; }

    public virtual Student Student { get; set; }
}

public class Professor 
{
    [Key]
    public int Id { get; set; }

    public virtual AspNetUser User { get; set; } // This is where you will be able to retrieve their name, email etc

    public string Profession { get; set; } 

    // Any other properties specific to a Professor
}
ediblecode
  • 11,701
  • 19
  • 68
  • 116
  • Thanks a lot. In that case I think there is no problem regarding to my approach. On the other and, I am wondering these points and I would be happy if you clarify me abut them >>> – Jack Jun 23 '16 at 11:00
  • **1)** I also add Type property to the AspNetUser table in order to determine that if the user Student or Professor. Then while creating a new user, I add a new record to the AspNetUser table and add another record to the Student or Professor table with the custom properties, is that true? **2)** If the 1st is true, do you suggest to use transaction in EF? **3)** When a user login to the system I look at the Type during authentication abd retrieve the detail data from the corresponding table. Is that true? Thanks... – Jack Jun 23 '16 at 11:00
  • @binary Unfortunately, these are all separate questions so you may want to ask new ones. However, do not create a Type property. In your `AspNetUsers` table you will have `public virtual Professor` and another for `Student` and then if one is null you will know which one it is. – ediblecode Jun 23 '16 at 11:03
  • Thanks for reply, but I do not understand what do you mean with your explanations about Type property. Could you please clarify a little bit more? – Jack Jun 23 '16 at 11:29