Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more.
Get startedGrow your Fabric skills and prepare for the DP-600 certification exam by completing the latest Microsoft Fabric challenge.
I am working on a Power BI project where I need to implement Row Level Security (RLS) to control what data users can see. The model is expected to serve up to 1000 users, thus performance is important. These users are not all expected to be concurrent users, but some proportion could be. The RLS filter uses the DAX function USERPRINCIPLENAME() to identify the logged in user, and filter data to just records related to their respective company.
Here is my PBIX file and below is a screenshot of my model:
In this model, I use "cross filter direction" set to "Both" in two relationships, which as I understand, will negatively impact the model performance. Microsoft's guidance on Bi-directional relationships indicates the same.
The RLS in my current model works fine, on the sample dataset (see screenshot).
I've investigated two approaches suggested by Reza Rad in his RLS book (link to book), to eliminate the need for bidirectional relationships. Specifically:
Unfortunately, both methods have yet to yield successful results.
Therefore I am looking for suggestions on how to eliminate the Bi-directional relationships.
Here's a brief overview of my data model:
I appreciate any insights or suggestions you might have to eliminate Bi-directional relationships from this model.
Thank you in advance!
Solved! Go to Solution.
@Anonymous
I think your use of bi-directional to drive RLS should be ok but I would combine the users together in a single table. It looks like it is always a UPN is related to 1 or more Company_ID so you should be able to combine those tables 'Client Manager' and 'Client Company Users' into 1 table.
You would need to add the field [Client Company ID] for the users in the 'Client Company Users' user table but then your master Users table would link on [Client Company ID]. It is faster for the model to traverse a relationship based on shorter field length so joining on [Client Company ID] is a better choice than using [Company Name].
I would also remove the GUIDS [ZAP employee ID] / [Unique User ID] unless you really need them. If they are not being used for anything then they are just taking up space in the model.
Another option would be to filter the company list from a disconnected user table using an filter on the company table like this.
VAR _UPN =
USERPRINCIPALNAME ()
RETURN
'Client Company'[Company ID]
IN CALCULATETABLE (
DISTINCT ( 'Users'[Client Company ID] ),
'Users'[Email Address] = _UPN
)
Again, I would do this against a single user table.
@jdbuchanan71 Great suggestions. I will test each suggestion. These changes, combined with load testing - as outlined in this Chris Web's post should hopefully cover off our needs.
@Anonymous
I think your use of bi-directional to drive RLS should be ok but I would combine the users together in a single table. It looks like it is always a UPN is related to 1 or more Company_ID so you should be able to combine those tables 'Client Manager' and 'Client Company Users' into 1 table.
You would need to add the field [Client Company ID] for the users in the 'Client Company Users' user table but then your master Users table would link on [Client Company ID]. It is faster for the model to traverse a relationship based on shorter field length so joining on [Client Company ID] is a better choice than using [Company Name].
I would also remove the GUIDS [ZAP employee ID] / [Unique User ID] unless you really need them. If they are not being used for anything then they are just taking up space in the model.
Another option would be to filter the company list from a disconnected user table using an filter on the company table like this.
VAR _UPN =
USERPRINCIPALNAME ()
RETURN
'Client Company'[Company ID]
IN CALCULATETABLE (
DISTINCT ( 'Users'[Client Company ID] ),
'Users'[Email Address] = _UPN
)
Again, I would do this against a single user table.
User | Count |
---|---|
88 | |
88 | |
75 | |
67 | |
58 |
User | Count |
---|---|
137 | |
110 | |
93 | |
84 | |
69 |