none
EF 5 - TPT Inheritance and CRUD Operations RRS feed

  • Question

  • Hello,

    I am using EF 5 on a project and I'm facing a little bit of a struggle regarding the modelling of my database and the classes on my application.

    I have two entities, User and Employee, both inheriting from an abstract class Person. All of these classes are mapped to their corresponding tables in the database. Both Users and Employees tables share the same primary key which is also the primary key of the People table.

    My application requires that an User can also be an Employee, but they can also exist separately. Up until now, I can add and retrieve Users and Employees with no problem.

    For example, I should add a new User and relate it to an existing Employee. How can I do that in terms of code? Should I use the Add method, or the EntityState notation? Also, if I need to delete either one of the entities, how can I assure that only the data specific to the entity will be removed, without messing up the People table?

    Thursday, December 19, 2013 4:05 PM

All replies

  • Hello,

    >>My application requires that an User can also be an Employee, but they can also exist separately

    Entity Framework does not support this such optional relationship. We have to set a relationship between entities or just leave them separate.

    >>For example, I should add a new User and relate it to an existing Employee. How can I do that in terms of code? Should I use the Add method, or the EntityState notation? Also, if I need to delete either one of the entities, how can I assure that only the data specific to the entity will be removed, without messing up the People table?

    For this, you can create a one-to-one or zero relationship using the fluent API. For detail regarding Configuring Relationships with the Fluent API, please refer to link below:

    http://msdn.microsoft.com/en-us/data/jj591620.aspx

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, December 20, 2013 8:33 AM
    Moderator
  • Hi Fred, I work with Lucas, and I'm trying to figure out how to address our issue.

    Let's try to focus on the design here, forgeting about EF, entities and tables, shall we?

    I mean, User and Employee share some data, but some data are specific to each one. The shared data could be expressed in terms of Person.

    Now, Employee can be an User; if you think, that makes sense, because the Employee can have access to the application, so it needs an login and password. However, the system's administrator can add Employee to the application without attaching an User to it, because that specific Employee won't have access to the application.

    Moreover, an User can be just that, an User; that is, it could has nothing to do with Employee. The system's administrator can add Users as he wishes, regardless if the User is an Employee.

    So, how can we express that in terms of tables and classes?


    Take a look at WPF FlashMessage
    About.me

    Tuesday, January 7, 2014 1:49 PM
  • In the relational model you can simply add the row to both the Employee and User tables with the same PersonID. But that's not going to work in the .NET model.

    In your .NET classes there's no way to express that a person can be a User and/or an Employee using inheritance. 

    So you need to use some other modeling technique for that.

    I would just make Employee and User separate.  One technique that can be useful here is to leave the abstract base class out of your DbContext.  This will cause EF to create completely separate tables to store Users and Employees, but will preserve substitutability in  your object layer.

        internal abstract class Person
        {
          public int ID { get; set; }
          public string Name { get; set; }
        }
        internal class User : Person
        {
          public string password { get; set; }
          public int? EmployeeID { get; set; }
          public Employee Employee { get; set; }
        }
        internal class Employee : Person
        {
          public string BadgeNumber { get; set; }
          public Employee Manager { get; set; }
        }
    
        internal class PersonModel : DbContext
        {
          //public DbSet<Person> Persons { get; set; }
          public DbSet<Employee> Employees {get;set;}
          public DbSet<User> Users {get;set;}
        }

    Notice here that the person attributes will not be synchronized between the two rows for an Employee/User.

    David


    David http://blogs.msdn.com/b/dbrowne/


    Tuesday, January 7, 2014 4:36 PM