Entity Framework many-to-many query: navigation property not generated - entity-framework-4

I have two tables User and UserRole which are they connected using a link table UserInRole
When I generate the entity model, for some reason, the entity UserInRole not getting generated. And as you can see from the picture, Entity Framework understood that there is many-to-many relationship between User and UserRole:
I need to implement the query like this
select ur.Name from [User] as u
inner join UserInRole uir on uir.UserId = u.Id
inner join UserRole ur on ur.Id = uir.UserRoleId
where u.Username = 'magename'
I am using generic repository, if navigation property would exists the query would be looking like this:
from u in repository.AsQueryable<User>()
join uir in repository.AsQueryable<UserInRole>() on u.Id equals uir.UserId
join ur in repository.AsQueryable<UserRole>() on uir.UserId equals ur.Id
where u.Username == userName
select ur.Name
But Entity Framework does not generate UserInRoles navigation property and related UserInRole entity, so the question what should I do in that situation? Should I remove link between UserInRole and UserRole to get entity UserInRole generated in model or there any way to have the query I described above without any changes in database?
UPDATED
so looks i need to do something like that
stirng[] roles = (from u in repository.AsQueryable<User>()
where u.Username == userName
select ur.UserRoles.Select(x => x.Name)).ToArray<string>();
getting an error Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<string>>' to 'string[]' any ideas?

You don't need that link table in your EF model! That's the beauty of EF!!
Check your entity User - it has a UserRoles navigation property - that's the collection of all roles this user is in.
Check out entity UserRole: it has a navigation property Users which has all users that are in this role.
With these two multi-valued navigation properties, you can express any of the queries you might want:
find all users for a given role (find the UserRole entity and enumerate its .Users property)
find all roles for a given user (find the User and enumerate its .UserRoles)
EF and the EDM sort of "hide" that link table from you - you don't really need it when you're expressing your intent in the conceptual model; those link tables are just a "necessary evil" in relational databases since those databases cannot model m:n relationships in any other way.
Update: so you seem to want to find a list of all the user roles (their names) that a particular user is in - you can express this something like this:
// find the user in your "dbContext" (or via your repository)
var user = _dbContext.Users.FirstOrDefault(u => u.Name == "magename");
// from the list of UserRoles on that user, select the names only
var userRolesNames = user.UserRoles.Select(ur => ur.Name).ToList();

Related

ASP.NET MVC controller join two tables: "An anonymous type cannot have multiple properties with the same name"

I have the following code to join two tables in an ASP.NET MVC controller but I also want to display employee's supervisor name from the same table and same filed.
But I get an error:
An anonymous type cannot have multiple properties with the same name
Here is my code
public IHttpActionResult GetEmployees()
{
var query = (from n in db.Employees
join c in db.tblCities on n.ProjectID equals c.CityID
into nc
from c in nc.DefaultIfEmpty()
join manager in db.Employees on n.ManagerName equals manager.Name
into pc
from managerin pc.DefaultIfEmpty()
select new
{
n.Name,
manager.Name,
n.Email,
c.CityName
});
var employees = query.ToList();
return Ok(employees);
}
What is the workaround to accomplish my goal?
You need to give the properties (or at least conflicting ones) actual names so you know what is what. Which Name would be Name if you don’t? For example:
select new
{
n.Name
ManagerName = manager.Name,
n.Email,
c.CityName
}
Also often it’s better to use actual types instead of anonymous ones so you get type safety properly through the application, especially when this information is given out to views etc.

MVC EF get many-to-many relationship table

I set up my many-to-many relationship in EF. But I can only refer to the main tables, not the bridge table. How can I refer to the bridge table?
for example:
User: UserID, name
Group: GroupID, group
UserGroup: UserID, GroupID
I can refer to the User table and Group table by typing
context.User.(some linq expression)
context.Group.(some lin1 expression)
But I cannot refer to the bridge table by typing
context.UserGroup
It would be great to know which versions of MVC and EF you are working with. Based on the assumption that its MVC 4 and EF5...
The point of a Join table is to keep referential integrity going. As #timothy says, there is no reason to refer to the (UserGroup) Join table unless there is actual additional data in it i.e. payload. If you're putting other data in the UserGroup table then its not a Join table anyway.
Rather use some Lazy or Eager loading to get the Group data you need:
Lazy Loading
var users = context.Users
foreach (User x in users)
{
foreach (Group f in x.Groups)
//notice the x user being referred to here for Groups
{
// Whatever you want to do with the objects
}
}
Eager Loading
var users = context.Users.Include(g => g.Groups)
foreach (User x in users)
{
foreach (Group f in x.Groups)
//notice the x user being referred to here for Groups
{
// Whatever you want to do with the objects
}
}
The 'foreach' code above is just added to show how to include it in a loop example. Its the first line of these Loading examples that are important.
Once you have defined 'var users' the rest is "easy".
Good Luck!
When defining a many-to-many relationship you have two options.
Link User to Group, and let it know that UserGroup is your join table
Link User to UserGroup as many-to-one, also link Group to UserGroup using many-to-one.
The reason to use option 2 is when you have something other than just the two IDs in the join table. An example I had recently was a SortOrder field.
When querying with a materialized join table, it feels a little clumsy:
context.User.Select(user => new {
Name = user.Name,
Groups = user.GroupJoins
.OrderBy(groupJoin => groupJoin.SortOrder)
.Select(groupJoin => groupJoin.Group.Name)
});
Why you want refer to that junction table...?!
If you want to get Users of a group:
var users = from u in db.UserGroups.Include("User").Include("Group")
Where u.GroupID == gid
select u;
And simply vice versa if you need Groups of a User:
var groups = from g in db.UserGroups.Include("User").Include("Group")
Where g.UserID == uid
select g;

Retrieve data from many to many relationship in asp.net mvc linq

I have problem retrieving data in many to many relationship using linq.
I have 3 tables
Employee
role
RoleInemployee
The third table has two columns: empid and roleid
An employee can assigned to multiple roles are stored in third table or you can say single role assigned to multiple employee.
I just want to retrieve employee who have particular role id using linq.
I'm using navigation property in employee model like
public virtual ICollection<Role> role {get;set;}
This navigation property give me role for particular employee but I want to retrieve employees data which is having a particular role is assigned.
Can any body help?
Count has an overload with a predicate as parameter, so you can do
var count = db.Employees.Count(emp=> emp.role.Any(r=> r.Id == 12));
Edit
to get employees with a particular role
var employees = db.Employees.Where(emp => emp.role.Any(r => r.Id == 12));
If I understood the question correctly you want to get the number of employees set to a particular role id using LINQ.
If your entity framework Employee class has a list of roles included -- you can do the following with your list of employees where 123 is the RoleID you are looking for:
employeeList.Where(x => x.Roles.Where(y => y.RoleID == 123)).Count();
EDIT: Removed RoleInEmployee code

ASP.NET MVC 3 with EF not recognizing the many to many join table

In my database I have a User table and then another table with something like roles. There is a many to many join table between them. When someone is making a new user they have to be able to select the role they want for the user. However EF is not letting me associate my user with this other table. I had a dropdown list, but when the role was selected an invalid enrty error came up saying the PKID was not the correct input.
I must be missing something in how EF works, or at least how it links to MVC 3
Generally speaking, when you have a many to many relationship you need a separate table to hold the two foreign keys.
So you might have:
User
------
ID
Name
Role
------
ID
Name
UserRoles
------
ID
UserID
RoleID
Why do you need a many to many relationship here? If I were you I'd create something like
User
------
ID
Name
IDRoleType
Role
------
ID
RoleType
That way a user can have a role, and in your code you can do something like:
public IQueryable FindUsers()
{
MyEntities db = new MyEntities();
return db.Users.Where(u => u.IDRoleType == 0);
}
Or
public IQueryable FindUsers()
{
MyEntities db = new MyEntities();
return db.Users.Where(u => u.Role.RoleType == "Admin");
}

How to handle relationships to users from other tables in ASP.Net MVC?

At the table level I'm setting aspnet_User.UserID as foreign key of UserID in the other tables (like Posts.UserID, so each post has an owner). Is that the way to go?
When I create the LINQ to SQL model, should I include the aspnet_User table?
When I create a post (record in the Posts table, a Post object), how do I set the relationship to the logged in user (User object in the controller)?
I don't include the aspnet_User table to my linq-to-sql as I don't really need it. I use the built in way of accessing membership data.
But for your table Posts, it might be easier for you to include it so that you can easily display the User's Name by doing myPost.User.Name
edit:
MembershipUser user = Membership.GetUser();
Guid userGuid = (Guid)user.ProviderUserKey;
Post post = new Post
{
UserId =userGuid,
Message = message
};
In your database schema, you should definately have a the UserID in the Post table be a foreign key to the aspnet_user table, on the UserID field. This way, you are making sure your data is clean. I would even add a cascade delete & update on that relationship.
Then, refer to my instructions in a previous question you asked, about how to get the user data.
(Thomas Stock summed it up briefly, above, though :) )

Resources