I am trying to expose the linked class that EF code first automatically creates in many to many relationships as a separate object because that linked object needs to be referenced in other classes, however I seem to have a problem with getting the data that exists in the database.
I've got the following 3 objects:
public class Role : Entity
{
public virtual ICollection<User> Users { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Permission> Permissions { get; set; }
}
public class User: Entity
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class UserRole : Entity
{
public User User { get; set; }
public Role Role { get; set; }
}
This creates the following tables:

Now I can see the problem is that it is creating a RoleUsers table, when it shouldn't and should just use my UserRoles table. How can I force the linked table to be UserRoles so that I can have that linked object exposed in EF so I can use it in other objects?
Also, how would I be traversing the objects then when writing queries? Would I still be able to use User.Roles.Any(y => y.Name == "blah"), or would I now have to query by going User.UserRoles.Any(y => y.Role.Name == "blah")? I suppose it isn't possible to maintain the transparent linking while simultaneously exposing the linked object?
Edit: One of the classes that references UserRole as a navigation property looks like this:
public class UserRoleEntity : Entity
{
public UserRole UserRole { get; set; }
public Guid EntityId { get; set; }
public EntityType EntityType { get; set; }
}
I don't want to individually store the User and Role object in this class because then they are not tightly coupled and data could be orphaned.
You don't need to explicitly create UserRole entity in your code. since you have the navigational property of Roles in Users and Users in Roles, EF will automatically create a relationship between them.
EDIT : If you want to create the link table and use that as a property of another class, you can do it like this.
public class User
{
public int UserID { set; get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
public class Role
{
public int RoleID { set;get;}
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
public class UserRole
{
public int UserRoleID { set; get; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}
public class AnotherEntity
{
public int ID { set; get; }
public int UserRoleID { set; get; }
}
and you will have your tables created like this

And you are correct, You have to access it like this
StringBuilder stRoleNames = new StringBuilder();
var user1 = dbContext.Users.Where(x => x.UserID == 34).SingleOrDefault();
var userRoles = user1.UserRoles;
foreach (var userRole in userRoles)
{
stRoleNames.Append(userRole.Role.Name);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With