Can I filter the Users returned by GetAllUsers based on a role they are in - linq

I am trying to create an administration interface where users and roles (among other things) can be administered. I have a list of users who can be edited, deleted or viewed. I have this code in the action:
var model = Membership.GetAllUsers()
.Cast<MembershipUser>()
.Select(x => new UserModel
{
UserName = x.UserName,
Email = x.Email,
UserRoles = Roles.GetRolesForUser(x.UserName)
});
return View(model);
This is all fine except that I don't want admins to be able to edit each other. So I need to filter out all users in the "super admin" role. I can certainly figure this out by stepping through each role for each user to see if they are a member. I am wondering if there is a nice sucinct way to do this by filtering the result set in the Select statement, or using Except or Where

I would normally think about the sql I want generated then try write the linq, filtering by roles should be fairly easy with a simple where statement.
However it appears you're trying to abstract each part of the query into smaller bits, this may make it easier to write but can have a devastating effect on performance. For example, I wouldn't be suprised if the GetRolesForUser method you are calling causing an extra database query per user that is returned by GetAllUsers, using the Include method is a much nicer way to get all roles at the same time.
var model = context.Users
.Include(user => user.UserRoles)
.Where(user => !user.UserRoles.Any(role => role == superAdmin)
.Select(user => new UserModel() { UserName = user.UserName, Email = user.Email, UserRoles = user.UserRoles});

Related

Parse: Get roles for an array of users

I have an array of users and I want to get each user's roles. For example, imagine my app displays a list of users and the names of their roles under their usernames. I cannot find any straightforward and cheap (without many requests) way to do this.
Query the roles. In most cases this will be one, small query.
For each user on your list, search the returned roles' users for that user. If you're searching on ID, you have all you need. (edit - removed reference to includeKey).
Can you not use a matchQuery. So from your list of users, use query to get all of user objects, and then use that query to get all of your roles. Once you have the roles, you can then match the roles to the users. I have gave the answer below for the Android SDK as you haven't specified which SDK you are using.
String[] userIds;
ParseQuery<ParseUser> innerQuery = ParseUser.getQuery();
innerQuery.whereContainedIn("objectId", userIds);
ParseQuery<ParseObject> query = ParseQuery.getQuery("Role");
query.whereMatchQuery("user", innerQuery);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> roleList, ParseException e) {
}
});
Obviously you would need to fill out the userIds variable with the userIds of all your users. To be honest you could even use any other query for the users that would return all the users you want.

Entity Framework Many-To-Many Join Query

I've got a standard social networking paradigm where a User has a collection of friends who are also users.
I'm using Entity Framwork Code First, and my Friend Relationship is defined as follows:
modelBuilder.Entity<User>()
.HasMany(u => u.Friends)
.WithMany()
.Map(m =>
{
m.ToTable("Friendships");
m.MapLeftKey("UserId");
m.MapRightKey("FriendId");
});
What I want to do is to search my users table returning all users with an indicator of whether each returned user is friends with the current user. To be clear, I want to return Users who are Friends and Users who are not friends, but also with a boolean indicating whether each user is a friend. I know how to do this in TSQL its a basic left outer join.
I've seen examples of how to do a left join in LINQ, but all the examples I've seen are joining to a mapped type. My Friendships column doesn't have a Mapped type.
How do I do this in EntityFramework?
var list = context.Users
.Where(u => u.Age >= 20) // sample condition, if you want ALL remove the line
.Select(u => new
{
User = u,
FriendOfCurrentUser = u.Friends.Any(f => f.UserId == currentUserId)
})
.ToList();
Result is a list of anonymous objects containing the user and the boolean friendship indicator. You can also create a helper class UserWithFriendship and project into it (Select(u => new UserWithFriendship { ... }) instead of an anonymous type.

Displaying records from database which are equal to logged on user

I have created an MVC3 application which needs to show user specific data. The problem I am having is trying to display records which are equal to #user.Identity.Name.
The following Linq to SQL has been used to try to accomplish this:
public ActionResult Index()
{
using (var db = new mydatEntities())
{
var details = from t in db.testadtas
where t.UserID == Viewbag.UsersRecord
select t;
return View();
}
}
(Update)
New to c# and Linq and finding it hard to write a query which will only display the logged on users records.
I have used the code below
MembershipUser currentUser = Membership.GetUser (User.Identity.Name, true /* userIsOnline */);
Viewbag.UsersRecord = currentUser.ProviderUserKey;
I have then input the Viewbag.UserRecord into a textbox which updates a database field with the UserID in a table I have created.
I now want to write a linq query to say if UserID = Viewbag.UserRecord then show record with the UserID only
Is this a correct method to use for showing logged on user records?
or is there any other way which I can implement this in MVC3?
Just use HttpContext.User.Identity.Name

LINQ - select query in related objects Entity Framework (EF4)

For the following (I'm using EF4) I need to select all messages in a Thread (ContactThreadId) that were NOT yet read given LoginId
So, i based on ContactThreadId and LoginId I need to know if this LoginId has already read all messages in a Thread. If not I need to update ContactReadState with all messages from the thread with his/her LoginId and when she/he read it.
I've tried these but am stuck:
// Update read state
var thread = this.contactMessageThreadRepository.GetRow(id);
var loginEntity = this.loginRepository.GetRow(ProfileContext.LoginId);
var unreadMsg = loginEntity.Contact
.Where(x => x.ContactThread.Any(y => y.ContactThreadId == id))
.Select(b => b.ContactMessage.FirstOrDefault())
.Where(q => q.ContactReadState.Count() == 0);
var unreadMsg = loginEntity.Contact
.Where(x => x.ContactThread.Any(y => y.ContactThreadId == id))
.Where(y => y.ContactReadState.Any(q => q.ContactId != loginEntity.ContactId));
var msg = thread.Contact
.Where(x => x.LoginId == loginEntity.LoginId)
.Where(y => y.ContactReadState.Count() == 0);
please help.
thanks
EDIT:
Login - this table hols logins/admin records
Contact - this table holds all contacts (including Login items because Logins can also participate in a conversation-can reply to messages etc.) When a LoginId in a contact table is NOT NULL, it means it's a Login user otherwise it's a public user submitting a message.
QUESTION -> Each Login can have only 1 Contact record (I have a trigger that creates a Contact record upon Login creation). How do I make it so that it's 1 to 1.??
I've added a FK from Contact to Login table but for some reason EF created 0..1 -> * association. And it should be 1 to 1. For a given Login there can be only 1 Contact with that LoginId.
Whenever Login is viewing a list of messages a new record is inserted to ContactReadState for that Login (marking a message read by that Login (with ContactId for that Login).
I have a fragment, but can't put it completely together. Especially I don't know how you would set the ContactId in the new ContactReadState objects (see ??? below) because apparently a given loginId can have many contacts. So, which one to set in the new read states? Probably I misunderstood something in your model, because all those relationships look very complicated to me.
...based on contactThreadId and loginId...
I'm using a context directly, you need to translate this into your repository structure:
using (var context = new MyContext())
{
var unreadMsgs = context.ContactMessages
.Where(cm => cm.ContactThreadId == contactThreadId
&& !cm.ContactReadState
.Any(crs => crs.Contact.LoginId == loginId))
.ToList();
// These should be the unread messages you want to select.
// Now, updating ContactReadState:
foreach(var unreadMsg in unreadMsgs)
{
var newContactReadState = new ContactReadState
{
ContactMessageId = unreadMsg.ContactMessageId,
ContactId = ???,
ReadDate = DateTime.Now
};
context.ContactReadStates.AddObject(newContactReadState);
}
context.SaveChanges();
}
Edit
If I understand correctly there can be contacts without login but if there is a login it is uniquely assigned to a contact.
Creating such a one-to-one relationship in EF correctly requires the following:
You must remove the LoginId column and the corresponding relationship from your Contact table (it's the reason for the one-to-many relationship EF creates).
The LoginId primary key column in the Login table must not be an autogenerated identity.
You must create a foreign key relationship between Contact and Login table where the foreign key column in Login is the primary key column LoginId at the same time. So, the relationship is between Login.LoginId (the "dependent" with the FK) and Contact.ContactId (the "principal" with the PK).
This would mean that a Login with LoginId=x refers to a Contact with ContactId=x (same value) which finally makes it easy to fill the ??? in the code snippet above: ??? is simply = loginId.
Edit 2
...and of course you can replace then in the query ...
.Any(crs => crs.Contact.LoginId == loginId)
...by...
.Any(crs => crs.ContactId == loginId)
(which avoids an unnessacary join to the Contact table)

How do you re-use select statements with Entity Framework?

Given the following query:
var query = from item in context.Users // Users if of type TblUser
select new User() // User is the domain class model
{
ID = item.Username,
Username = item.Username
};
How can I re-use the select part of the statement in other queries? I.e.
var query = from item in context.Jobs // Jobs if of type TblJob
select new Job() // Job is the domain class model
{
ID = item.JobId,
User = ReuseAboveSelectStatement(item.User);
};
I tried just using a mapper method:
public User MapUser(TblUser item)
{
return item == null ? null : new User()
{
ID = item.UserId,
Username = item.Username
};
}
With:
var query = from item in context.Users // Users if of type TblUser
select MapUser(item);
But if I do this, then the framework throws an error such as:
LINQ to Entities does not recognize
the method 'MapUser(TblUser)' method,
and this method cannot be translated
into a store expression.
You can't use regular function calls in a query definition like that. LINQ needs expression trees, it can't analyze compiled functions and magically translate that to SQL. Read this for a more elaborate explanation
The techniques used in the cited article are incorporated in linqkit (factoring out predicates) and might be of help, though I'm not sure you can use the same technique for managing projections, which is what you seem to want.
The more fundamental question you should ask yourself here IMHO is whether you really need this extra mapping layer? It seems like you're implementing something that EF is already perfectly capable of doing for you...
Try making your MapUser method static.

Resources