6

I'm trying to understand the best way to define my POCO classes to be able to use Entity Framework code-first feature.
I want to define some foreign key relations in my classes, between the user and also between the classes themselves. For example consider the following 3 classes:

Public class Job
{
    public int JobID {get; set;}
    public string JobTitle {get; set;}
    public virtual ICollection<Resume> Resumes {get; set;} // Is this correct at all? How to access all resumes for a certain job? (many-to-many relationship between Job and Employee)
}

Public class Resume
{
    public int EmployeeID {get; set;} // or should it be: public virtual Employee EmployeePerson?
    public int JobID {get; set;} // or should it be: public virtual Job UserJob?
    public DateTime EmploymentDate {get; set;}
}  

public class Employee
{
    public int EmployeeID {get; set;}
    public int UserID{ger; set;} // or should it be: public virtual MembershipUser User?
    public ICollection<Resume> Resumes {get; set;} // Is this correct at all? 
}

The user is a Membership user which is in System.Web.Security which is being authenticated by FormsAuthentication or ActiveDirectoryAuthentication. The questions are mentioned in the code (as comments). But for clarification:

  • Should I define the objects in relations and use .Include every time I need them or is it better to store the ID of the objects and try to get the data from that ID every time I need to? Should I use a different approach when dealing with MembershipUser class instead of my defined classes?
  • What's other uses of virtual apart from enabling lazy loading? Where should I avoid it and where should I use it?

Thank you.

UPDATE: I have just tested to define Employee with the ublic virtual MembershipUser User definition. The result was 4 added columns in my table:

  • User_Email,
  • User_Comment,
  • User_IsApproved,
  • User_LastLoginDate,
  • User_LastActivityDate

Nothing unique to the user (User_Email is defined as nullable). So If you want to have user in you classes, write a wrapper for MembershipUser or just store UserID.
Thank you Ladislav and Sergi.

Kamyar
  • 18,123
  • 8
  • 90
  • 164

2 Answers2

5

I would recommend declaring the Foreign Keys as navigation properties, that way you can always access the related property directly without having to retrieve it explicitly from the database yourself (it will be lazy loaded).

So your model would look like:

public class Resume
{
    public int ID {get; set;}
    // or should it be: public virtual Employee EmployeePerson? 
    // --> yep, easier for you, innit?
    public Employee Employee {get; set;} 

    // or should it be: public virtual Job UserJob? --> yep :)
    public virtual Job Job {get; set;}

    public DateTime EmploymentDate {get; set;}
}  

public class Employee
{
    public int EmployeeID {get; set;}

    // or should it be: public virtual MembershipUser User? 
    // --> yes, as an approach, but read on for clarification.
    public virtual MembershipUser User {get; set;}

    // Is this correct at all? ---> needs to be declared as virtual
    public virtual ICollection<Resume> Resumes {get; set;}
}

Your Job class is OK as far as I can tell.

To be clear, it will work as well using it as you had it initially, but you'll need to explicitly mark the properties with the ForeignKeyAttribute, which isn't necessary if you're willing to give up a tiny bit of control on how FK's are named in your database.

  • One remark about the MembershipUser navigation property: I'm afraid you'll need to write a wrapper for the MembershipUser class because as far as I can recall it doesn't have a default contructor and so EF will probably not be able to instantiate it for you on lazy loading.

  • About the effects of marking a property as virtual, you might want to take a look at this question: What effect(s) can the virtual keyword have in Entity Framework 4.1 POCO Code First?

Community
  • 1
  • 1
Sergi Papaseit
  • 15,434
  • 14
  • 62
  • 99
3

In case of code first I would probably use this:

public class Job
{
    public virtual int JobId {get; set;}
    public virtual string JobTitle {get; set;}
    public virtual ICollection<Resume> Resumes {get; set;} 
}

public class Resume
{
    [Key, Column(Order = 0)]
    public virtual int EmployeeId {get; set;}
    [Key, Column(Order = 1)] 
    public virtual int JobId {get; set;} 

    public virtual DateTime EmploymentDate {get; set;}
    public virtual Employee Employee {get; set;}
    public virtual Job Job {get; set;}
}  

public class Employee
{
    public virtual int EmployeeId {get; set;}
    public virtual int UserId {ger; set;} 
    public virtual User User {get;set;}
    public virtual ICollection<Resume> Resumes {get; set;} 
}

Foreign keys in entity are bad but they make things much easier in EF. If you don't use foreign key property EF will define different type of relationship. Virtual keyword on navigation property is for lazy loading and virtual keyword on other mapped properties is for change tracking.

Community
  • 1
  • 1
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654