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
Related
I am attempting to build a web app that allows users to view company policies, procedures, newsletters, and their own employee information.
I have my staff table that contains all the employee information (along with related lookup tables for things like prefix, staff grade, etc)
my app uses asp-identity for the login functionality, but I want to be able to return information from the staff table that is only relevant to that particular user.
I know it is possible to extend the ASP.net users table to include custom fields, but this doesn't really suit my goal as the staff table is used in a desktop based app by the admin team.
Add a field to your Staff table UserId for example ALTER TABLE Staff ADD UserId NVARCHAR(256) DEFAULT NULL;
Optionally, you would reference the AspnetUsers table.
Update Staff table rows in other to set UserId values to related users ids (manually or create an action to do that)
Then, In your the controller, you can select newsletter from table where employee's user id equal connected User.Identity.Id. for example
var news = context.Newsletters.Where(n=>n.Staff.UserId==User.Identity.Id);
var infos = context.StaffInfos.Where(si=>si.Staff.UserId==User.Identity.Id);
in case the tables are not in relationship, you'll need to do like following
var employee = context.Staffs.FirstOrDefault(s => s.UserId == User.Identity.Id);
if(employee != null) {
var infos = context.StaffInfos.Where(si=>si.IdEmployee==employee.EmployeeId);
return View(infos);
} else {
return Content("You don't have an account associated to your staff info...");
}
Please replace fields in these queries with the names of your fields.
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;
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();
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");
}
I have a model, Docs, with a guid column, author_id, which should reference a MembershipUser.
I'm using the standard MembershipProvider (I only changed the db name), and of course I haven't a model for MembershipUsers.
I can easily define some methods in class Docs to get MembershipUser for a Doc and all Docs for a MembershipUser, but some things are tricky (listing users, show how many docs each user has); furthermore, I feel I'm using MVC in an odd way: it seems to me that it would be easier if I had a MembershipUsers model...
How can I implement this relationship? Should I implement a model for MembershipUsers?
thanks
update: I realize I wasn't clear at all.
Say I want to list all my users and their docs.
One way to do this is:
ViewModel model = new ViewModel()
{
Users = from MembershipUser user in Membership.GetAllUsers(page, pagesize, out totalusers)
select new UserWithDocs
{
User = user,
Docs = context.Docs.Where(c => c.author_id == (Guid) user.ProviderUserKey)
},
UsersCount = totalusers
};
This works, but generates one separate query for each user.
I could get an array of users' guids and then query for Docs where author_id IN list_of_guids, but then I should manually associate each doc to its author.
What is a better solution?
not sure if i understand you correctly, but you can use the MembershipUser class as your model for users. if you want to reference user to your "doc" model, you can simply add a property "Author" to you model class and when you fetch the model from DB you can get the user as well.
the Membership class contains some static methods to list all users, add/delete users etc.