Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code-First - Defining relationships with MembershipUser

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.

like image 839
Kamyar Avatar asked Apr 12 '11 09:04

Kamyar


People also ask

How do you create a foreign key relationship in code first approach?

To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table.

How do I code first in Entity Framework?

Step 1 − First, create the console application from File → New → Project… Step 2 − Select Windows from the left pane and Console Application from the template pane. Step 3 − Enter EFCodeFirstDemo as the name and select OK. Step 4 − Right-click on your project in the solution explorer and select Manage NuGet Packages…


2 Answers

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?

like image 53
Sergi Papaseit Avatar answered Oct 12 '22 00:10

Sergi Papaseit


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.

like image 25
Ladislav Mrnka Avatar answered Oct 11 '22 22:10

Ladislav Mrnka