Well it's a noob question but i can't figure out the solution.
I have two entities, user and team. User can create a team and invite other users. User can belong only one team but team has multiple users.
What would be the most correct relationship between users and team? I also need DateJoin in team and other properties. Should i create third table(TeamMembers)?
Here is code what i tried :
public class TeamMember
{
public int Id { get; set; }
[ForeignKey("Team")]
public int TeamId { get; set; }
public Team Team { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public User User { get; set; }
public DateTime DateJoin { get; set; }
public RoleEnum MemberRole { get; set; }
}
public enum RoleEnum
{
Capitan = 1,
Main,
Sub
}
And team has list of members:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public int Score { get; set; }
public ICollection <TeamMember> Members { get; set; }
}
But third table means many to many relationship...
If the user can only belong to one team then this is the correct format.
However, if you think you might change this policy in the future then I do suggest you use a many to many relationship. This would also allow you to keep track of the previous teams your users belonged to, by simply using a "DateLeave" property for example.
Related
I am trying to build an organization hierarchy where each team might contain one or many members and/or one or many sub-teams.
To do so, my model is:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Members { get; set; }
public virtual ICollection<Team> SubTeams { get; set; }
public Employee Manager { get; set; }
}
When adding a migration and updating database, everything seems logical in the table.
EF has added an extra nullable column "Team_Id" where the Id of the parent Team gets stored.
My question is about getting the Id of the parent Team from my model.
I tried adding:
public int? Team_Id
To my model, but EF considered it as a model change and asked for another migration.
How can I get the value of column Team_Id in my model? getting this info takes too much processing when looping through teams.
I always add foreign key in my model. When it adds to the model, EF won't add Team_Id .
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Members { get; set; }
public virtual ICollection<Team> SubTeams { get; set; }
public Employee Manager { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public Team ParentTeam { get; set; }
}
I hope this example be helpful.
Suppose I have two entities, bungalows and apartments. Both of them have varying fields and cannot be interchanged however both these entities have multiple tenants. Each tenant can only be part of either one bungalow or one apartment. How do I achieve this using Entity Framework?
I was thinking of creating 2 more entities bungalowTenants and apartmentTenants and using these to map. Each bungalowTenant would have one instance of a bungalow and a tenant and similarly for apartmentTenant.
Bungalows would have a collection of bungalowTenants and apartment of apartmentTenants.
public class Bungalow
{
public int Id { get; set; }
public int HouseNumber { get; set; }
public string Street { get; set; }
public ICollection<BungalowTenants> Tenants { get; set; }
}
public class Apartment
{
public int Id { get; set; }
public int ApartmentNumber{ get; set; }
public string Wing{ get; set; }
public string Building{ get; set; }
public ICollection<ApartmentTenants> Tenants { get; set; }
}
public class Tenant
{
public int Id{ get; set; }
public string Name{ get; set; }
}
public class ApartmentTenants
{
public int ApartmentId { get; set; }
public Apartment Apartment{ get; set; }
public int TenantId{ get; set; }
public Tenant Tenant{ get; set; }
}
public class BungalowTenants
{
public int BungalowId{ get; set; }
public Bungalow Bungalow{ get; set; }
public int TenantId{ get; set; }
public Tenant Tenant{ get; set; }
}
The problem with this approach is that it does not restrict in any way the same tenant to be a part of both, a bungalow and an apartment. I am unable to figure out how to do that using Entity Framework. I'd appreciate any help on this matter.
Not every business rule can be or needs to be translated to database constraints or model constraints.
And if you would enforce this, through model rules or programmed rules:
What if the tenants decide to move from a bungalow to an apartment? They will most probably want to start renting the new home days or even weeks before the cancellation date of the old one - or do you expect them to vacate the old home before midnight and enter the new home after midnight, with all their belongings packed in boxes on the pavement for a certain period? That does not seem very realistic.
My stack is ASP.NET MVC 5, Entity Framework 6.1, code-first, SQL Server.
I'm working on an application which involves multiple schools, each of which have courses (each which have sections) and students. These form hierarchies of related objects, which are each rooted by a single school instance.
Basic layout so far:
One school has many courses and students
One course has many sections
Simplified versions of the models follow.
public class School
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int Id { get; set; }
public int SchoolId { get; set; }
public virtual School School { get; set; }
public virtual ICollection<Enrolment> Enrolments { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public int SchoolId { get; set; }
public virtual School School { get; set; }
public virtual ICollection<CourseSection> CourseSections { get; set; }
}
public class CourseSection
{
public int Id { get; set; }
public int CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual ICollection<Enrolment> Enrolments { get; set; }
}
There are other models and relationships involved, but this should be enough to form the basis for my question.
A course section is related to a course, which in turn relates to a school. Given a course section, I can determine the school it belongs to, e.g. var school = givenSection.Course.School. Conversely, given a school, I can get the course sections belonging to the school. In code it's just a couple of references away, while in the database it's just a couple of table joins. But it gets more interesting still. Consider the next model:
public class Enrolment
{
public int Id { get; set; }
public int StudentId { get; set; }
public int CourseSectionId { get; set; }
public virtual Student Student { get; set; }
public virtual CourseSection CourseSection { get; set; }
}
An Enrolment instance is the many-to-many bridge between students and course sections. Getting a list of enrolments for a school is multiple steps requiring multiple table joins. In a system which might become quite large in number of records, I worry about the efficiency of this setup. Then again, the application is configured for lazy loading, so maybe that's OK, I don't yet know enough about EF to be certain.
In the interest of simplicity for data retrieval, might it be ideal to reference the school from either of, or both, the CourseSection and Enrolment models? Extending it further, should all models in the hierarchy be able to directly reference the School they belong to?
No, that would break normalization. Your performance concern is valid but the solution cannot be known and should not be implemented prematurely and without measuring actual timings. In my opinion the data is the most important thing because chances are it will outlive the code. Therefore all else equal the good shape of the data should be e priority.
I am trying to use CodeFirst to generate my database.
I have two tables Staff and Team, There is one Team Leader in each team that is a foreign key to a staffID, and each staff is associated to one Team.
public class Staff
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string Token { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public bool Admin { get; set; }
public bool Active { get; set; }
public int TeamID { get; set; }
[ForeignKey("TeamID")]
public Team Team { get; set; }
}
public class Team
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public int TeamLeaderID { get; set; }
[ForeignKey("TeamLeaderID")]
public Staff TeamLeader { get; set; }
}
Because each one is pointing to the other I get an error Unable to determine the principal end of an association between the types 'Team' and 'Staff'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations. How do I annotate it in such a way that it understands why I am doing this.
Think about it this way... what comes first the team or the team leader? If you try to create a team leader you can't because you have to first specify a team! But if you want to create a team you can't because you must specify who the team leader is according to your foreign key constraints.
You will have to ease up in some way and either make it so that a team can have an optional team leader, or a staff member can optionally belong to a team.
You do this by changing one of the foreign key IDs to a nullable type:
public int? TeamLeaderID { get; set; }
Your code seems like you are trying to include business rule enforcement/responsibility via referential integrity. You have a one to many relationship your Team -> Staff. You just add a boolean for the TeamLeader. Your logic before doing a database write should check to see if you have an existing TeamLeader or not already.
public class Staff
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string Token { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public bool Admin { get; set; }
public bool Active { get; set; }
public IsTeamLeader { get; set; }
}
public class Team
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
//virtual keyword tells Code First to create the proper Foreign Key relationship
public virtual List<Staff> Members{ get; set; }
}
If you had a large system, with many developers, you could use the fluent API to accomplish your goal and enforce your team leader rule at the database level, thus preventing an out of touch developer from inadvertently adding a second team leader to any give team but if this is a small to normal size project, with small teams that are aware of the basics of the company/project than a simple one to many relationship will accomplish the mission and you can rely on your business rules/logic to enforce/protect the database data so that there is one team leader for any given team at any give time. Consider an AddUpdateTeamMember type method that is called by everyone that enforces the team leader requirement. A stored procedure is another great way to easily solve this problem if you are still considering a model first approach and still experimenting with code first.
Consider too, what if there was a need for two team leaders on one team at some future point of time in the project, database might get too inconveniently "locked down" to scale to this change.
Consider this Poco:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
}
Now i want to implement a follow technique where a user may follow other users so basically its self Many to Many relationship
problem is i don't know how exactly i can achieve this in Entity Framework Code-First ?
I thought of a linker Table :
public class UserFollow
{
public int Id { get; set; }
public int Follower { get; set; }
public int Following { get; set; }
public DateTime FollowDate { get; set; }
}
i want to be able to get All Followers and Following from every User Object?
This is quite simple using EF code-first as you only need the User POCO:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
public ICollection<User> FollowedUsers { get; set; }
}
The collection means that a User is related to other users.
PS: I noted you added a timestamp in your solution example. To achieve that you should still add the collection changing the generic type to whatever suits your needs.
Hope it helps.