I am very new to ASP.net I am trying to use MVC. I have a method that gets the current users information from a sql database using Linq. How would I get those result into the view and use them anywhere in the site?
My method to get user information:
public List<AspNetUser> GetCurrentUser()
{
FulfillmentContext db = new FulfillmentContext();
string username = HttpContext.Current.User.Identity.GetUserName();
var currentUser = (from u in db.AspNetUsers
join ur in db.AspNetUserRoles on u.Id equals ur.UserId
join r in db.AspNetRoles on ur.RoleId equals r.Id
where u.UserName == username
select u).ToList();
return currentUser;
}
Ideally you should load it up in your model:
public ActionResult Index()
{
FulfillmentContext db = new FulfillmentContext();
string username =
HttpContext.Current.User.Identity.GetUserName();
var currentUser = (from u in db.AspNetUsers
join ur in db.AspNetUserRoles on u.Id equals ur.UserId
join r in db.AspNetRoles on ur.RoleId equals r.Id
where u.UserName == username
select u).First();
var model = new Model();
model.CurrentUser = currentUser;
return View(model);
}
However, you can create a HTML helper extension:
public static AspNetUser GetCurrentUser(this HtmlHelper helper)
{
FulfillmentContext db = new FulfillmentContext();
string username = HttpContext.Current.User.Identity.GetUserName();
var currentUser = (from u in db.AspNetUsers
join ur in db.AspNetUserRoles on u.Id equals ur.UserId
join r in db.AspNetRoles on ur.RoleId equals r.Id
where u.UserName == username
select u).First();
return currentUser;
}
Then call it from your view:
#{
var user = Html.GetCurrentUser();
}
Related
users = (List<UserResponse>)
(from u in _context.Users
join rolePermiss in _context.RolePermissions on u.RoleId equals rolePermiss.RoleId
group new { u, rolePermiss} by u.Id into gr
select new UserResponse()
{
Id = gr.FirstOrDefault().u.Id,
//Permissions = gr.FirstOrDefault().rolePermiss.Select(x => x.Id).ToList()
}).ToList();
try this linq
users = (List<UserResponse>)
(from u in _context.Users
join rolePermiss in _context.RolePermissions on u.RoleId equals rolePermiss.RoleId
group new { u, rolePermiss } by u.Id into gr
select gr.FirstOrDefault() into mr
select new UserResponse()
{
Id = mr.u.Id,
//............
}).ToList();
I have a sample to look into Async calls and i need to get a count from the sub query. I know how to write this in a TSQL query but i am bit confused with the iqueryable use.
Here is what i currently have. I am getting the users and then get the count inside a loop. How can i do the loop part in the first query?
public static async Task GetUsers(this List<UserViewModel> users)
{
var db = ApplicationDbContext.Create();
users.AddRange(await (from u in db.Users
select new UserViewModel
{
Id = u.Id,
Email = u.Email,
FirstName = u.FirstName,
LastName = u.LastName
}).OrderBy(o => o.Email).ToListAsync());
if (users.Any())
{
foreach(var user in users)
{
user.SubscriptionsCount = await (from us in db.UserSubscriptions
join s in db.Subscriptions on us.SubscriptionId equals s.Id
where us.UserId.Equals(user.Id)
select us).CountAsync();
}
}
}
Could be handled in one of the following two ways. I have picked #2 for my sample.
1 : with sub query
var singleQuery = from u in db.Users
join sub in (from us in db.UserSubscriptions
join s in db.Subscriptions on us.SubscriptionId equals s.Id
group us by us.UserId into countGroup
select new { Count = countGroup.Count(), UserId = countGroup.Key })
on u.Id equals sub.UserId into sub1
from subR in sub1.DefaultIfEmpty()
select new UserViewModel
{
Id = u.Id,
Email = u.Email,
FirstName = u.FirstName,
LastName = u.LastName,
SubscriptionsCount = subR.Count == null ? 0 : subR.Count
};
var siteUsersSub = await (query).OrderBy(o => o.Email).ToListAsync();
2: Composing from sub queries
var subQuery = from us in db.UserSubscriptions
join s in db.Subscriptions on us.SubscriptionId equals s.Id
group us by us.UserId into countGroup
select new { Count = countGroup.Count(), UserId = countGroup.Key };
var query = from u in db.Users
join sq in subQuery on u.Id equals sq.UserId into sq1
from sqR in sq1.DefaultIfEmpty()
select new UserViewModel()
{
Id = u.Id,
Email = u.Email,
FirstName = u.FirstName,
LastName = u.LastName,
SubscriptionsCount = sqR.Count == null ? 0 : sqR.Count
};
var siteUsers = await(query).OrderBy(o => o.Email).ToListAsync();
I've this query:
var usersByBranch = (from u in _db.VRT_User
join urb in _db.VRT_UserRoleBranch on u.UserId equals urb.UserId
join r in _db.VRT_Role on urb.RoleId equals r.RoleId
where branches.Contains(urb.BranchId)
select new UserRoleBranchModel
{
UserId = u.UserId,
BranchId = urb.BranchId,
RoleId = urb.RoleId,
RoleName = r.RoleName
});
In this query, for the same userId, the roleId (1-4) and RoleName with the same BranchId are returned separately.
I'd like to flatten the rows, so that a row with the same userId contains all the RoleId and RoleName within the same BranchId.
Your help is greatly appreciated.
Not sure what you mean by contains, but you can't use the same UserRoleBranchModel to hold multiple roles, so an anonymous object will do the job:
var usersByBranch = (from u in _db.VRT_User
join urb in _db.VRT_UserRoleBranch on u.UserId equals urb.UserId
join r in _db.VRT_Role on urb.RoleId equals r.RoleId
where branches.Contains(urb.BranchId)
group r by new { urb.UserId, urb.BranchId } into rg
select new {
UserId = rg.Key.UserId,
BranchId = rg.Key.BranchId,
Roles = rg.Select(r => r)
});
var usersByBranch = (from u in _db.VRT_User
join urb in _db.VRT_UserRoleBranch on u.UserId equals urb.UserId
join r in _db.VRT_Role on urb.RoleId equals r.RoleId
where branches.Contains(urb.BranchId)
group u by u.UserId into g
select new UserRoleBranchModel
{
UserId = g.Key,
BranchId = g.First().BranchId,
RoleId = g.First().RoleId,
RoleName = g.First()RoleName
});
In my database I have roles and users, I also have user roles to tie the 2 together.
The problem is trying to get all users with their roles (if they have any, which they may not).
I use this query:
return (from ur in db.UserRoles
join r in db.Roles on ur.RoleID equals r.ID
group r by ur.UserProfileID into ugr
join u in db.UserProfiles on ugr.Key equals u.ID
select new UserModel() {
ID = u.ID,
Username = u.UserName,
IsLockedOut = u.IsLockedOut,
LastLoginDate = u.LastLoginDate,
UserRoles = (from r in ugr
select new RoleModel() {
Name = r.Name,
ID = r.ID
}).ToList()
}).ToList();
This works for users who have at least one role, but I also want users who do not have roles.
I'm currently trying to use http://msdn.microsoft.com/en-us/library/bb397895.aspx DefaultIfEmtpy(), but I don't know how and where to place it, meaning however I try my code does not compile.
How do I get all my Users, even if they do not have any UserRoles linked to them?
Get the users first and include their roles from then
return db.UserProfiles
.Include(up => up.UserRoles)
.Select(u => new UserModel() {
ID = u.ID,
Username = u.UserName,
IsLockedOut = u.IsLockedOut,
LastLoginDate = u.LastLoginDate,
UserRoles = u.Roles
.Select(r => new RoleModel() {
Name = r.Name,
ID = r.ID
})
})
.ToList();
Update based on comments
return db.UserProfiles
.Include(up => up.UserRoles)
.Include("UserRoles.Roles") // <-- Added further include
.Select(u => new UserModel() {
ID = u.ID,
Username = u.UserName,
IsLockedOut = u.IsLockedOut,
LastLoginDate = u.LastLoginDate,
// Modified this to use joining table
UserRoles = u.UserRoles
.Select(ur => new RoleModel() {
Name = ur.Role.Name,
ID = ur.RoleID
})
})
.ToList();
Right now I have 3 tables: User, Roles, and User_Roles for the many-to-many association. I want to create a search function that takes in a list of RoleIDs and return Users with that role. But if the RoleID list is empty, it should return all Users.
This is what I have so far..
public static List<User> SearchUser(List<int> roleIDs)
{
List<User> userList = new List<User>();
using (var db = new DBContext())
{
var users = (
from u in db.Users
join ur in db.User_Role
on u.UserID equals ur.UserID
join r in roleIDs
on ur.RoleID equals r
select u
).Distinct().ToList();
}
return userList;
}
but I can't figure out a way to conditionally join to User_Role only when roleIDs is not empty.
I also tried this but it didn't work.
var users = (from u in db.Users
from r in roleIDs
join ur in db.User_Role
on u.UserID equals ur.UserID
where roleIDs.Count == 0 || ur.RoleID == r
select u
).Distinct().ToList();
Is it possible to have a conditional join in Entity Framework?
Treat each case separately.
public static List<User> SearchUser(List<int> roleIDs)
{
using (var db = new DBContext())
{
if (roleIDs.Count == 0)
{
return db.Users.ToList();
}
var users = (
from u in db.Users
join ur in db.User_Role
on u.UserID equals ur.UserID
join r in roleIDs
on ur.RoleID equals r
select u
).Distinct().ToList();
return users;
}
}
You can simplify the join as follows if the join table is not mapped as separate entity.
public static List<User> SearchUser(List<int> roleIDs)
{
using (var db = new DBContext())
{
if (roleIDs.Count == 0)
{
return db.Users.ToList();
}
var users = db.Users.Where(u => u.Roles.Any(r => roleIDsContains(r.Id)))
.Distinct().ToList();
return users;
}
}
My biggest was concern keeping the code maintainable as new search criteria is added and to minimize the database calls. I ended up using if statements but didn't load it from the database till the very end. This resulted in one large sent query. I forced the database call by calling .ToList() at the end.
public static List<user> SearchUser(List<int> roleIDs, List<int> hobbyIDs)
{
List<User> Users = new List<User>();
IQueryable<User> tempUsers = null;
using (var db = new DBContent())
{
tempUsers = db.Users;
if (roleIDs.Count > 0)
{
tempUsers = from u in tempUsers
join ur in db.User_Role on u.UserID equals ur.UserID
join r in roleIDs on ur.RoleID equals r
select u;
}
if (hobbyIDs.Count > 0)
{
tempUsers = from u in tempUsers
join uh in db.User_Hobby on u.UserID equals uh.UserID
join h in hobbyIDs on uh.HobbyID equals h
select u;
}
//Go get it from the database
Users = ((ObjectQuery<User>)tempUsers)
.Include("Address").Distinct().ToList();
}
}