[DevExpress Support Team: CLONED FROM T1054371: Q359904: How to modify objects/properties in code when the user does not have the permission seems to not work.]
Hello Andrey,
I have a last question: could you please tell me how to force "reloading" all related associated collections of an object without using an external call?
I mean something like:
C#payCard.Reload()
Thanks in advance.
D
Hello,
It is not clear what you mean by 'external call' here. Refer to the article that describes how to reload XPO collections: How XPO reloads objects and collections. Please let me know if you require any clarification.
Thanks,
Andrey
Hi Andrey,
Sorry if I was unclear. With "external call" I would refer the line you added to explicitly load the associated objects in the "lst" variable:
var lst = new XPCollection<PayCardUsage>(e.Session).ToList(); foreach (PayCard payCard in cardsToUpdate) { payCard.CalculatePayMoneyAmount(true); }
What I want to achieve is something like:
foreach (PayCard payCard in cardsToUpdate) { payCard.RELOAD()?? (What I can use here to reload all the paycard's collections including also the "protected" objects?) payCard.CalculatePayMoneyAmount(true); }
I'm asking if there is a way to perform a reload of all the associated collection within the nonsecure session avoiding adding explicit loading query like the one you did with the lst variable.
Thanks
D
Hi,
As far as I understand, you mean that when you access nested collections, additional SQL queries are used to fetch them. You wish to load these collections without additional requests. If so, use the Session.PreFetch method to load the nested collections in a single request.
If I still misunderstand the issue, would you please capture a screencast to illustrate the issue in action with your project from the following ticket: Q359904: How to modify objects/properties in code when the user does not have the permission seems to not work.?
Hi Gosha,
I modified the original example, please find it attached.
Now please do this:
As you can see in the method:
public void CalculatePayMoneyAmount(bool ischanged) { Session.PreFetch(Session.GetClassInfo<PayCard>(), PayCardUsages, nameof(PayCardUsages)); _PayMoneyAmount = PayCardUsages.Sum(s => s.PayMoney); if (ischanged) OnChanged("PayMoneyAmount"); }
despite I added a call to the session.Prefetch method asking to reload the PayCardUsages collection, you will see that, due to the ObjectPermission rule, the PayCardUsages is still empty and the resulting value of the Sum will be zero instead of 1000.00.
Being that we are within a non secured session, what I want to achieve is simply having the PayCardUsages collection loaded will all the values regardless the security permissions set.
Thanks in advance for your support.
D
After searching within the APIs I think that the best way to ensure having all the PayCardUsage objects in the collection regardless the security permissions is using the following method:
public void CalculatePayMoneyAmount(bool ischanged) { (new XPCollection(Session, this, Session.GetClassInfo<PayCard>().FindMember(nameof(PayCardUsages)))).Load(); _PayMoneyAmount = PayCardUsages.Sum(s => s.PayMoney); if (ischanged) OnChanged("PayMoneyAmount"); }
Do you agree or you have additional hints?
Thanks
D
Hello D,
Thank you for sharing the sample project. We need additional time to research it and check the solution you described. We will get back to you as soon as we get any results.
Hi,
From what I gather, I should log in as "user" to reproduce the issue, and the following security permission prevents the PayCardUsages collection from being loaded:
userRole.AddObjectPermissionFromLambda<PayCardUsage>(SecurityOperations.FullObjectAccess, o=>o.PayMoney==1000, SecurityPermissionState.Deny);
With this permission, the "Not [PayMoney] = 1000.0m" criterion is applied to the collection, and the Session.PreFetch method will not help here.
Creating a new XPCollection seems to be the right solution, but you need to create filter criteria to load the PayCardUsages collection only for the current PayCard object. Here is an example:
public void CalculatePayMoneyAmount(bool ischanged) { var payCardUsages = new XPCollection<PayCardUsage>(Session, CriteriaOperator.Parse("PayCard = ?", this.Oid)); _PayMoneyAmount = payCardUsages.Sum(s => s.PayMoney); if (ischanged) OnChanged("PayMoneyAmount"); }
Let us know if this helps.
Thanks,
Stanley
Hello,
You are right.
What I want to avoid is specifying the Criteria ("PayCard = ?") that is already builtin in the collection "PayCardUsages" of the PayCard object.
Could you tell me if my above proposal is acceptable or if you see any side effect?
Thanks
D
Hello D,
The XPCollection(Session, Object, XPMemberInfo) constructor is used in our code to get associated collections. If you use it in your code, you will get the same result. However, note that it is intended for internal use.
Thanks, is seems to be the best solution except when the original collection is not yet loaded.
In the above case neither my suggested method:
(new XPCollection(Session, this, Session.GetClassInfo<PayCard>().FindMember(nameof(PayCardUsages)))).Load();
or your suggested method:
var payCardUsages = new XPCollection<PayCardUsage>(Session, CriteriaOperator.Parse("PayCard = ?", this.Oid));
works. It is necessary to load the original collection first then use one of the above methods.
Thanks
D