Problem with linq2sql Group-By then Where - c#

I'm trying to get the user records that do NOT have the current role. A user can have multiple roles.
I'm working with 2 tables - Users and UserRoleMap
var superAdminRoleId = *GUID*
var query = from user in _userRepository.Table
join userRoleMap in _userRoleMapRepository.Table
on user.Id equals userRoleMap.UserId
// Now, group the roles by the user
group userRoleMap by user into userRoleMaps
// get the records that are NOT super admin
where !userRoleMaps.Any(map=>map.UserId == superAdminRoleId)
select userRoleMaps.Key;
I'm getting the error
LinqToDB.LinqToDBException: ''map.UserId' cannot be converted to SQL.'
So I revised it to
var query = from user in _userRepository.Table
join userRoleMap in _userRoleMapRepository.Table
on user.Id equals userRoleMap.UserId
// Now, group the roles by the user
group userRoleMap.UserId by user into userRoleMaps // changed userRoleMap to userRoleMap.UserId
// get the records that are NOT super admin
where !userRoleMaps.Any(map=>map == superAdminRoleId) // update
select userRoleMaps.Key;
Now, I'm getting
System.ArgumentException: 'Property 'System.Guid Id' is not defined for type 'System.Guid' (Parameter 'property')'

There's probably a way to fix your group by, but looking at what it seems you're trying to accomplish I think you'll get a better-performing and simpler query like this:
var userRoleMaps = _userRoleMapRepository.Table;
var nonAdminUsers = _userRepository.Table
.Where(user => !userRoleMaps
.Any(map => map.UserId == user.Id && map.RoleId == superAdminRoleId));

Related

How to add condition to LINQ query based on Id

This is my action method which fetches all the users with their Id.
public JsonResult GetUsers()
{
var ret = (from user in db.Users.ToList()
select new
{
UserName = user.UserName,
// i am stuck here, i want to get all those ids whom current logged user is following
Idfollowing = user.FollowTables.Contains()
Idnotfollowing =
});
return Json(ret, JsonRequestBehavior.AllowGet);
}
the structure of FollowTable is like this:
ID UserId FollowId
1 4 11
2 4 12
2 4 13
here, current loggedin user's id is 4 and he is following 11, 12, 13 so i want to return only 11, 12 and 13 to Idfollowing and rest remaining id in the Idnotfollowing. how to get it done.
Well, i think with list or array, i will not get desired result. so, i want to add something here.
Well, with every UserName an id is also passed to view page. So, i have break them into two.Now, how to assign values to these ids.
Comapre User.Id with Current loggedin user's follow table's followId column.If match is found .i.e if id matches or found then assign that user.Id to Idfollowing and null to Idnotfollowing and vice versa in opposite case.
I have to generate follow unfollow button based on these ids returned.
public JsonResult GetUsers()
{
int currentUserId = this.User.Identity.GetUserId<int>();
var ret = (from user in db.Users.ToList()
let Id = user.FollowTables.Where(x => x.UserId == currentUserId).Select(f => f.FollowId).ToList()
let Idnot = (from user2 in db.Users
where !Id.Contains(user2.Id)
select user2.Id).ToList()
select new
{
UserName = user.UserName,
Id = Id,
//Id = user.FollowTables.Where(x => x.UserId == currentUserId)
// .Select(x => x.FollowId).Single(),
Idnot = Idnot,
It looks like you have a standard one-to-many relationship from User to FollowTable. This data model enforces that user.FollowTables only contains followers. You won't be able to fill in Idnotfollowing from the FollowTables property directly.
Something like this may work:
var query = (
from user in db.Users // note: removed ToList() here
// to avoid premature query materialization
where //TODO ADD WHERE CLAUSE HERE ?
let followIds = user.FollowTables.Select(f => f.FollowId)
let notFollowIds = (from user2 in db.Users
where !followIds.Contains(user2.Id)
select user2.Id)
select new
{
UserName = user.UserName,
Idfollowing = followIds.ToArray(),
Idnotfollowing = notFollowIds.ToArray()
})
// TODO add paging? .Skip(offset).Take(pageSize)
.ToList();
Do verify the SQL generated by this query and make sure it performs ok though...
Also, note that I removed the .ToList() from db.Users.ToList() to avoid premature query materialization. It is generally a bad idea anyway to extract all data from a table unconstrained, you will typically want to a
var ret = (from user in db.Users.ToList()
select new
{
UserName = user.UserName,
Idfollowing = user.FollowTables.Select(x=> x.Id)
Idnotfollowing = db.FollowTables.Where(x=> !user.FollowTables.Select(x=> x.Id).Contains(x.Id)).Select(x=> x.Id)
});
it's ugly but will work, there must be another better way to do.
You can simply use a Where method to filter the table and use Select to project FollowiId:-
var ret = (from user in db.Users.ToList()
select new
{
UserName = user.UserName,
Idfollowing = user.FollowTables.Where(x => x.UserId == user.Id)
.Select(x => x.FollowId).ToArray(),
Idnotfollowing = user.FollowTables.Where(x => x.UserId != user.Id)
.Select(x => x.FollowId).ToArray()
});
Assuming, Idfollowing & Idnotfollowing are array if integers (if FollowId is integer) otherwise you can replace it with ToList if its a list instead.

ASP .NET Identity 2.0 and LINQ compound query with group by

I am using ASP .NET Identity 2.0 as my user manager. Right now I want to retrieve the list of all users with RoleId different from "4". My LINQ query looks like this:
var userList = from entry in this.UserManager.Users
from roles in entry.Roles
where roles.RoleId != "4"
group entry by entry.Id into g
select new { g.Id, g.UserName, g.Email, g.EmailConfirmed, g.PhoneNumber, g.PhoneNumberConfirmed, g.Roles };
Unfortunately, group by completely doesn't work and g's parameters are not recognized. Without grouping the list contains separate rows for every user->role and it is not my desired effect. What is wrong in my query?
Edit:
Of course each user has a number of roles. If one of them is RoleId == 4 then I do not want his record to be retrieved.
I don't see any need for grouping. Try this much simpler query:
var userList = this.UserManager.Users
.Where(u => u.Roles.All(r => r.Id != "4"));
This should give you the result you are looking for.
var userList = (from entry in this.UserManager.Users
//group entry by entry.Id into g //I don't know why you need to group this,usually `id` is primary key
select new { entry.Id, entry.UserName, entry.Email, entry.EmailConfirmed, entry.PhoneNumber,
entry.PhoneNumberConfirmed, Roles=entry.Roles.Where(r=>r.RoleId != "4").ToList() })
.Where(g=>g.Roles.Count>0);
if there is no role's in result, the user will be removed

Linq, Joining a list to last item in another list

I have a list of Users and another list of users activities.
I want to get list of users including user last activity.
I tried this:
var usersActivity =
from user in Users
join activity in Activities on user.Id equals activity.UserId
group activity by activity.UserId into UserActivities
select new {
activity=UserActivities.OrderByDescending(g=>g.DateTime).First(),
user=user
}
But it does not works. it says: The name 'user' does not exist in the current context
Am I wrong in joining or grouping?
Try grouping by user instead of user ID:
var usersActivity =
from user in Users
join activity in Activities on user.Id equals activity.UserId
group activity by user into UserActivities
select new
{
activity = UserActivities.OrderByDescending(g => g.DateTime).First(),
user = UserActivities.Key
};
You can use a simpler approach:
var usersActivity =
from user in Users
select new {
activity=Activities.Where(a => a.UserId = user.Id).OrderByDescending(a => a.DataTime).FirstOrDefault(),
user=user
}

Difficulty accessing data from twiitter using LinqToTwitter

I am using the following code in C#
var users = (from user in twitterCtx1.User
where user.Type == UserType.Lookup &&
user.UserID == list1
select user)
.ToList();
The list1 has all the IDs of the verified accounts of twitter and I am processing 75 records at a time. when I debug my code, I see that the list1 is populated with all the IDs but when the control passes in this portion of the code, it does not enter inside the it as the value being passed here is NULL
I am not able to understand as to why the value is NULL. What am I missing here?
Thanks in advance!
You're comparing user.UserID to the entire list1 object. Did you mean to write list1.Contains(user.userID)?
I'm still not clear on what error you're seeing, but here are some tips that might help.
list1 needs to be a string that is a comma-separated list of user IDS. Here's some code to show how it works:
var followers =
(from user in twitterCtx.SocialGraph
where user.Type == SocialGraphType.Followers &&
user.ScreenName == "JoeMayo"
select user)
.SingleOrDefault();
var userIDs = string.Join(",", followers.IDs.Take(100).ToList());
var users =
(from user in twitterCtx.User
where user.Type == UserType.Lookup &&
user.UserID == userIDs
select user)
.ToList();
First, the demo gets a list of user IDs. It's a user object with an IDs collection of type ulong. The next statement creates a comma-separated string of 100 of those IDs. Finally the lookup assigns that comma-separated string to the UserID property.
You should examine list1 and verify that it's a properly formatted comma-separated string of user IDs. The max size is 100.

How can i do it using linq2sql...?

I have a table Users. Users has a column rating. How i can get information about user place using linq2sql? I want method like:
var userPlace =
GetUserPlaceById(userId);
Table Users may contains a few thousands users.
Sorry guys. Users DOESNT contain place column. Real example: Rating is chess elo rating. if you have high rating then you on 1st place. If you have lower rating then you on the last place.
Did you mean something like this?
int userRating = users.Single(user => user.Id = userId).Rating;
int userPlace = users.Where(user => user.Rating < userRating).Count() + 1;
I have a table Users. Users has a column rating. How i can get information about user place using linq2sql?
I'm not sure what "userPlace" is, but assuming it is a column in that table...
var userPlace = (from user in db.Users
where user.Id == userId
select user)
.First()
.UserPlace;
Be aware that calling .First() will throw an exception if no match is found, so if you expect that sometimes this user will not exist use FirstOrDefault, check for null, and then grab the UserPlace property.
You would use something like:
string GetUserPlaceById(int userId)
{
IQueryable<User> users = GetUsers(); // Get users queryable reference
return users.Single(user => user.Id == userId).Place;
}
You could do something like this:
var userPlace = _db.Users.Where(x => x.UserId == userId).Select(x => x.Place).SingleOrDefault();

Categories

Resources