Entity Framework Code-First - Defining relationships with MembershipUser
D

2

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.

Deification answered 12/4, 2011 at 9:55 Comment(0)
N
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?

Nonexistence answered 12/4, 2011 at 11:58 Comment(3)
Thank you Sergi, Haven't noticed MembershipUser doesn't have a default constructor.Deification
@Kaymar - You're welcome. BTW, I said it off the top of my head, so don't take my word for it. Do check! :)Nonexistence
@Kaymar - Just checked: it does have a default constructor but it is protected, so for all purpose and intent, it hasn't ;)Nonexistence
I
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.

Insalivate answered 12/4, 2011 at 18:41 Comment(8)
Thanks Ladislav. How Does EF behave about public virtual User User in Employee table? does EF define it as a complex type?Deification
Is it a complex type or entity?Insalivate
It is a MembershipUser which is defined in .NET in System.Web.Security namespaceDeification
@Ladislav: I tried it and the result is 4 rows in my table. I'll update the question...Deification
And do you want to store all properties from membership user in employee table or do you want to have relation to membership table?Insalivate
@Ladislav: I just want to have a relationship. Do you suggest any better way than the one I have mentioned in my question's update section?Deification
If you want relation user can't be mapped as complex type but as navigation property to other entity. This would require mapping membership user as entity.Insalivate
@Ladislav: Thank you! I've learned many new things by reading you posts.Deification

© 2022 - 2024 — McMap. All rights reserved.