MVC EF get many-to-many relationship table - asp.net-mvc

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;

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.

Is it possible to reference another table so that an employee record is associated with a user record?

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.

How to access 2 tables' relationship in a view in MVC

In my program I have two tables/models: Users and Groups in a many-to-many relationship.
When someone is logged in, I want to expose certain links that only Users in that specific Group can access.
Now in my view if I do:
#using (var dbContext = new DatabaseContext())
{
var user = dbContext.Users.First(p => p.Id == SecurityContext.CurrentUser.Id);
if (user.Groups.Count() < 1)
Debug.WriteLine("Less than 1");
}
And the list is always empty.
Is this something that view models are meant for? I need to somehow access both tables to find if a certain user is in a certain group.
You have to load related entities
var user = dbContext.Users.Include("Groups").First(p => p.Id == SecurityContext.CurrentUser.Id);
Read more about loading related entities on MSDN

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

Entity Framework many-to-many query: navigation property not generated

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();

Resources