How join tables with many to many relationships - c#

What I'm trying to do is to is join tables to fill a viewModel that looks like this:
public class UserViewModel
{
public String Id { get; set; }
public String UserName { get; set; }
public String Email { get; set; }
public String Role { get; set; }
}
My query atm looks like this, but it doesn't work obviously, but it might help with descriping the problem.
public IActionResult AddAdmin()
{
var allUsers = (from u in _dbContext.Users
join r in _dbContext.UserRoles on u.Id equals r.UserId
join i in _dbContext.Roles on r.RoleId equals i.Id
select new UserViewModel
{
UserName = u.UserName,
Email = u.Email,
Id = u.Id,
Role = i.Name
}).ToList();
return View(allUsers);
}
As you see the thing I find hard is to apply the role to the viewModel, since they are connected to eachother with a manyTomany Table
Problem: The query does not work, and does not give anything in result
Before I joined the role into the viewModel, i got the data to the view, now i get nothing at all.
My Question: What's the correct way to do this? To easily navigate through the data

When I did it like this, it worked...
public IActionResult AddAdmin()
{
var allUsers = (from u in _dbContext.Users
select new UserViewModel
{
UserName = u.UserName,
Email = u.Email,
Id = u.Id
}).ToList();
foreach (var item in allUsers)
{
var roleId = _dbContext.UserRoles.Where(x => x.UserId == item.Id).FirstOrDefault();
item.Role = _dbContext.Roles.Where(x => x.Id == roleId.RoleId).FirstOrDefault().Name;
}
return View(allUsers);
}
I know it looks like s***..

You need a third entity to tie the two together. In Database terms, it is called a junction table.

Related

How to join table in LINQ with aspnetusers and then create new object with results for ViewModel

just want to know what I should be adding in the select new block to retrieve SQL query result.
I have a BlogViewModel, and two tables blog and users. I want to join the two tables get the result and then have this in a object I can pass to View.
public IActionResult Index()
{
List<BlogViewModel> blogs = _db.blog.ToList(); //add elements into blogs list
List<IdentityUserHelper> users = _db.Users.ToList(); //add elements into users
var result = from b in blogs //"blogs" is list
join u in users //"users" is list
on b.userID equals u.Id into group1 //join tables blogs with aspnetusers
select new //below is object initliazer
{
//I want to join table with aspnetusers?? don't know what to put in here
};
var blogList = new List<BlogViewModel>(); //create list for blogs
foreach (var test in result) //iterate through queryresult
{
blogList.Add(new BlogViewModel
{
blogID = test.blogID,
blogContent = test.blogContent
userID = test.userID
}
);
public class BlogViewModel
{
[Key]
public int blogID { get; set; }
public string title { get; set; }
public string blogContent { get; set; }
public string author { get; set; }
public string userID { get; set; }
public DateTime publishedDate { get; set; }
}
You can select desired fields for the result with the desired aliases:
var result = from b in blogs
join u in users
on b.userID equals u.Id into group1 //join tables blogs with aspnetusers
select new //below is object initliazer
{
blogID = b.blogID,
blogContent = b.blogContent,
userID = b.userID,
author = u.Name
};
also, you can select new BlogViewModel directly in the result instead of select new and you won't need using foreach in order to return list of BlogViewModel items.
You certainly don't need foreach loop here. Try this
var model = from b in blogs
join u in users
on b.userID equals u.Id into bj
from b in bj.DefaultIfEmpty()
select new BlogViewModel
{
blogID = b.blogID,
blogContent = b.blogContent
userID = u.userID
author =u.Name
}
};
return View(model);

Left Join Linq query conditions not filtering

I'm trying to do a left join that is 1 user record has 1 (if it's there) contact Record associated with it. When this runs, it still pull multiple contacts ignoring my condition of 'where c.RecordType == "USR"'.
public class Users
{
public int Id { get; set; }
... other properties
public Contact Contact { get; set; }
}
public class Contact
{
public int Id { get; set; }
public int RecordID { get; set; }
public string RecordType { get; set; }
[ForeignKey("RecordID")]
public Users User { get; set; }
}
Linq Query
var query3 = (from c in db1.Contacts
join u in db1.Users
on c.RecordID equals u.Id
into a
from b in a.DefaultIfEmpty(new Models.Users())
where c.RecordType == "USR"
&& b.Lastname.Contains(name)
&& b.Active == 1
select new
{
b.Id,
b.FirstName,
b.Lastname,
b.FullName,
b.Contact
}).ToList();
Any help with where I'm going wrong would be much appreciated.
Thanks,
Adam
You can do a join in linq without using the join keyword. I use the following construct for left joins and do not have any issues.
var query3 = (from c in db1.Contacts
from u in db1.Users.Where(x => c.RecordID == x.Id).DefaultIfEmpty()
where (c.RecordType == "USR")
&& u.Lastname.Contains(name) && (u.Active == 1)
select new
{
u.Id,
u.FirstName,
u.Lastname,
u.FullName,
u.Contact
}).ToList();
As per information in question
1 user record has 1 (if it's there) contact Record associated with it
that means, a user can have zero or more contacts, so you suppose to use User as main entity and then left join on Contacts. Also you should apply Contact type filter during JOIN itself, like below
var query3 = ( join u in db1.Users
from c in db1.Contacts
on new { Record = c.RecordID, Type = c.RecordType } equals new { Record = u.Id, Type = "USR"} into b
from cont in b.DefaultIfEmpty(new Models.Contacts())
where u.Lastname.Contains(name)
&& u.Active == 1
select new
{
u.Id,
u.FirstName,
u.Lastname,
u.FullName,
cont.Contact
}).ToList();

Need to change sql server query into linq

select TeamName, [Description], COUNT(u.UserId)
from Team t
left outer join [User] u on u.TeamId=t.TeamId
group by TeamName, Description, UserId
and here i have so far but cant able to do that.please help
var countUser = (from t in db.Teams
join u in db.Users on u.TeamId equals t.TeamId
group TeamName, Description, UserId by select
new
{
u.UserId
}).Count();
This should do it:
Teams.Join(Users.DefaultIfEmpty().
t => t.TeamId,
u => u.TeamId,
(t, u) => new { t.TeamName, t.Description, UserId = u == null ? null:(int?)u.UserId })
.GroupBy(x => x)
.Select(g => new { g.Key.TeamName, g.Key.Description, Count = g.Count() });
RePierre I'm going to steal part of your answer (+1) because I think I understand what OP is talking about, though the question text does not convey it.
You could do something like this:
// Model class for View
public class UsersPerTeamCount
{
public string TeamName { get; set; }
public string Description { get; set; }
public int Count { get; set; }
}
// ...
public ActionResult PlayersPerTeam()
{
var model = from t in db.Teams
join u in db.Users on t.TeamId equals u.TeamId into joinedRecords
select new UsersPerTeamCount()
{
Name = t.TeamName,
Description = t.Description,
PlayerCount = joinedRecords.Count()
};
return View(model);
}
As far as in OPs comment "please try to write as like..." that's just a difference in syntax, it doesn't really matter which way you write it - either fluent vs query syntax (at least i think it's called query syntax)

Inner Join Between Many to Many Relationship Models

I have two model like below that are configured as many to many relationship:
public class Permission
{
public int PermissionId { get; set; }
public string PermissionName { get; set; }
public virtual List<Role> Roles { get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string Name { get; set; }
public string ID { get; set; }
public virtual List<Permission> Permissions { get; set; }
}
I want to do an Inner Join with Linq. I can do that easily in SQL since the join table is present there. But how can I do this with linq? Below is what I could do so far:
from pr in Permissions
join role in Roles on pr.Roles.Select(s => s.RoleId).FirstOrDefault() equals role.RoleId
select new { pr.PermissionName, role.RoleId }
As you can see above the FirstOrDefault will ruin the result but other than that I cannot get to compile the query without errors.
Below is the query I am trying to write in Linq:
SELECT P.PermissionName, R.RoleId
FROM Permissions AS P
INNER JOIN PermissionRoles AS PR ON P.PermissionId = PR.Permission_PermissionId
INNER JOIN Roles AS R ON PR.Role_RoleId = R.RoleId
As you can see, an inner join is made with the join table thus query works as expected
Any help is appreciated.
The easiest syntax is
from p in context.Permissions
from r in p.Roles // notice the p !
select new { p.PermissionName, r.RoleId, Role = r.Name, etc... }
EF will produce SQL with the required inner joins.
The fluent equivalent is
Products.SelectMany(p => p.Roles,
(p, r) => new
{
p.PermissionName,
r.RoleId,
...
})
You'll probably agree that the first form, "comprehensive syntax", wins.
var x = from pr in Permissions
from role in Roles
where pr.Roles.Exists(r => r.RoleId == role.RoleId)
select new { pr.PermissionName, role.RoleId };

Retrieving the username from MembershipUser for a join query

I'm newer using C#, linq. I'm trying to add the UserName into a query to show it as part of a DataSource of a ListView, I have tested several way to joined, but always I m'receiving next error:
"Unable to create a constant value of type 'Web.Admin.system.User'. Only primitive types or enumeration types are supported in this context."
My code is:
//Entities
public class Category
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Order
{
public Guid Id { get; set; }
public string Description { get; set; }
public Guid CategoryId { get; set; }
public Guid UserId { get; set; }
}
//class added just for getting the user list (possibly, I do not need)
public class User
{
public Guid Id { get; set; }
public String Name { get; set; }
}
Here is my code preparing the filter
//retrieve the data from Order and Category
IQueryable<Order> orders = orderService.GetAllOrders();
IQueryable<Category> category = categoryService.GetAllCategories();
//obtain the users
MembershipUserCollection members = Membership.GetAllUsers();
// 1st option for managing users directly with memberShip variable
var memberShip = members.Cast<MembershipUser>().ToDictionary(m => m.ProviderUserKey, m => m.UserName).AsQueryable();
// 2nd option, I have added this code to see if I could manage the users as a list
List<User> users = new List<User>();
foreach (var _member in memberShip)
{
users.Add(new User { Id = (Guid)_member.Key, Name = _member.Value });
}
//Getting information to fill a listview
var DDLsource = from i in orders
join c in category on i.CategoryId equals c.Id
join u in users on i.UserId equals u.Id // 1st I tried to use memberShip directly but gave me error of types
select new
{
i.Id,
i.Description,
CategoryName = c.Name,
UserName = u.Name
};
ListViewOrders.DataSource = DDLsource.ToList();
Here is where the Error is triggered, I'm trying to understand the error and do other solution, I tested the query like:
Example 2
var DDLsource = from i in orders
join c in category on i.CategoryId equals c.Id
select new
{
i.Id,
i.Description,
CategoryName = c.Name,
UserName = (from u in users where u.Id == i.UserId select u.Name)
};
Example 3
var DDLsource = from i in orders
join c in category on i.CategoryId equals c.Id
join u in Membership.GetAllUsers().Cast<MembershipUser>() on i.UserId equals ((Guid)u.ProviderUserKey)
select new
{
i.Id,
i.Description,
CategoryName = c.Name,
UserName = u.UserName
};
all with the same results, could someone give me a hand with my mistake will surely be very obvious. Thanks in advance
I would do something like this (sorry, untested code...):
var DDLsource =
from i in orders
join c in category on i.CategoryId equals c.Id
select new
{
i.Id,
i.Description,
CategoryName = c.Name,
i.UserId,
UserName = ""
};
foreach(var ddl1 in DDLsource)
ddl1.UserName = Membership.GetUser(ddl1.UserId).Name;

Categories

Resources