Execute multiple queries then union them with LINQ? - linq

I'm trying to build a drop down list that holds available options (i.e. a page category that a user can create a page for) for the logged in user, however, these are based on user roles due to the nature of how our business works - of which a user can belong to multiple roles and each role can have different options to select from in the drop down list.
What I'd like to do for users that are in multiple roles is combine the options of each individual role and use it as the values for the drop down list.
What I have assumed is that I would be able to run multiple LINQ queries by say running them through a for each (For Each r In userRoles) and then unioning them?
Though I don't know if this is possible in the way I'm trying to do it.
Is it possible or am I barking up the wrong tree?
Can someone please please please point me in the right direction?

It sounds like you could join user on roles and options and then group on options.
Something like this
Dim userId = GetCurrentUserId
Dim userOptions = From userRole In UserRoles
Join roleOption In RoleOptions
On userRole.roleId Equals roleOption.roleId And
userRole.userId Equals userId
Group By OptionId = roleOption.optioId, OptionName = roleOption.name
Into UserOptions = Group
Order By OptionName
I'm not a VB.NET coder and that is totally untested but hopefully you get the idea.

Related

PowerBI RLS - Multiple View based on Roles

I am working on a PowerBI report which requires RLS.
To simplify, let's say I have the following tables:
Table 1:
Sales, Account, ProductOwnerAccount, Owner, Region
Table 2
Userid, UserRegion, UserAccount
Scenario: Need to show two sets of tabular data:
All Rows Where Account = UserAccount and Region = UserRegion
All Rows where ProductAccount = UserAccount, Account <> UserAccount and Region = UserRegion
The only way to achieve this seems to be RLS and using two roles with corresponding DAX filters.
However, if I apply two roles to the same user, the least restrictive one takes precedence and hence, both report will give the same result.
I tried to create a calculated table, but that does not allow using USERPRINCIPLENAME as a filter.
I also tried to have a page level filter which could use a measure (which in turn uses USERPRINCIPLENAME()), this is also not allowed.
Similarly, a calculated column on each row to specify if it's owned by the current user doesn't work.
Is there any other way? Am I missing something very basic?

Parse - avoid sharing information in specific column of a class

I've got a question about the best way to allow user's information to be visible between users in certain situations.
I have certain columns in User class which are private to the user.
In some activity i'm pointing to user object as 'postedBy' or something else,In this case the entire data regarding user is getting shared.
My question is how to restrict user to get some columns in User class??
usually if you want to restrict an access in parse it should be done via ACL. In ACL you can create role for users who can read/write to the class.
ACL are executed on a class level and not on a column level. In order to expose part of the fields i think you have 2 options:
Create one to one realtionship from your User class to another Class. the second class will contain all columns that not all users can see and for this class create ACL's with the users/roles that can view this data and when you will execute your query only the users with sufficient permissions will be able to get this data
The second option is when you want to avoid relationships here you can use the select option under query. Select allows you to select specific fields of the class and the query will return only the fields that you specified under the select. here is a code snippet from parse docs which explain how to use select (in JS):
var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
query.select("score", "playerName");
query.find().then(function(results) {
// each of results will only have the selected fields available.
});
Hope its clear now :)

Runtime join in lightswitch

I have a generic group members table with a GUID for a "group type" and a GUID for "referenced object". An example would be if I have a table of customers(each having a GUID) I can group them under "already paid" by creating a group GUID and in my "Group members table" referencing every customer by their respective GUID. This allows for any type of group to be added to the model as we expand(without adding extra tables).
Here is the problem. I have created a subquery in an entity in order to filter the universal group members table for a certain group and what "items" are and are not in that group; like so:
partial void ElementsNotMemberOfGroup_PreprocessQuery(int? UniversalGroupTypeIDParameter, int? UniversalGroupsIDParameter, ref IQueryable<UniversalGroupMember> query)
{
query = query.Where(x => x.UniversalGroup.UniversalGroupType.UniversalGroupTypeID == UniversalGroupTypeIDParameter);
query = query.Where(x => x.UniversalGroup.UniversalGroupsID != UniversalGroupsIDParameter);
}
This returns the GUIDs for the referenced object in the group, but for a user that's useless. I need to join this table and my customers table at runtime on the GUID so I can extract the customer info and display it.
Any Ideas?
LightSwitch wasn't really created with this kind of scenario in mind. LightSwitch makes things very easy for you when you create relationships between tables that are, well, "related". When you do this, you never need manual joins between entities.
While it's possible to do something similar to what you're describing (see the link below), it's a lot more work to achieve it, and in my opinion it isn't really worth the extra trouble. Not only that, but as you're discovering, it complicates even the most simple operations.
In essence, you're working against LightSwitch, instead of with it. My advice to you would be that if you really must do this type of manual optimization, then LightSwitch may not be the best product for you to use.
Beth Massi has a blog article, Using Different Edit Screens Based on Record Types (Table Inheritance), which isn't exactly what you're doing, but it may give you some ideas if you decide to still use LightSwitch for your project.

How to connect a users table correctly to a Membership table, or should you even do that?

I'm probably going about this the wrong way, please feel free to correct me.
Currently I have a User model called U_USER, it contains fields such as address, receiveNotifications, HasCompanyCar Etc.
These users have roles in a .NET Membership table. When the user logs in via Membership, I get their user record in my database as follows (the username on the Membership table and my own U_USER table will have a match):
//Gets the current user
public U_USER CurrentUser()
{
return GetUser(HttpContext.Current.User.Identity.Name);
}
//Gets user details by username
public U_USER GetUser(String username)
{
return (from u in db.U_USER
where u.UserName == username
select u).FirstOrDefault();
}
If I wanted to get a list of all users in, lets say, the "Create" role then I would do this:
allUsers.Where(x => Roles.IsUserInRole(x.UserName, "Create"))
This is a big performance hit as it's doing a lookup for each iteration of a user. This makes me think I'm not going about user management in the correct way. So to answer this question:
How should you properly connect Membership to a users table that in turn is connected to the rest of your data? I'd also accept how to just go about it more efficiently!
Many thanks :)
EDIT :
I've increased performance via the below code. I get the users in the role in one swoop and then filter them.
String[] usersInRole = Roles.GetUsersInRole("CanApprove");
users = users.Where(x => usersInRole.Any(y => y == x.UserName));
But I'm still fairly sure I'm going about this ALL wrong!
Not an expert in this, but what my apps typically do is to use a foreign key (with Index) from my own Users table to the Membership Users table using the Guid field with the Membership. This then allows me to do queries using Linq like:
var query = from myUser in MyUsers
join aspUser in aspnet_Users on myUser.UserId equals aspUser.UserId
join usersInRole in aspnet_UsersInRoles on aspUser.UserId equals usersInRole.UserId
join role in aspnet_Roles on usersInRole.RoleId equals role.RoleId
where role ...
select new { ... };
(Or you can use dot-form like myUser.AspUser.Roles.Role to let the ORM generate the joins if you prefer)
For performance, it's good to watch the SQL trace occasionally - make sure you're not making too many SQL round-trips for each logical step in code.
Hope that helps a bit.
Update - in answer to your questions about "should you even do that", I think "yes" but there are other options available - e.g. you can use Profile fields - see Step 6 in this great walkthrough - https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
We have created EntityFramework entities for all of the AspNet membership tables, this lets us query them like any other entity.
Not sure if it is what your after but may help

one to many relationship in Entity Framework on the same table

I have two tables, in which one user can have several contacts:
User(UserId, UserName)
Contact(UserId, ContactId)
Suppose I would like to get all the ContactNames from the UserNames in the User Table by the Userid.
Note that the Contact table cannot be seen in the current data context, it has been turned into a many to many relationship
How can I do the query?
What If I need to insert or delete?
I tried the "include" method but it does not work. Do you have any suggestions?
Thank you very much.
var id = 1; // id to find
context.Users
.Where(x=>x.UserId = id)
.SelectMany(x=>x.Users)
.Select(x=>x.UserName)
.ToArray();
After generation from db your model has 2 sub-collections: Users and Users1.
One of it corresponds to users, that are contacts for current user.
Another stores users, that current user is contact for.
You can rename them to represent their meaning to Contacts and ContactsFor via editor.
If you still want to have 2 types instead of Type+(Many-To-Many Ref), then in editor you can delete reference, create new entity Contact, setup all mapping, add references. After all this is done - you will have model look like this:
To Achieve this:
Delete Many-To-Many reference
Crete new Entity Contact
Add properties ContactId and UserId, set StoreGeneratedPattern to none
Add mappings for Contact
Add associations for Contacts and ContactFor
But it's not that easy.

Resources