In my application, I have an extended Many-To-Many relation
scenario, where Aircraft is being used by Party in particular time interval
described in relation table AircraftInclusion. It means Aircraft -->>
AircraftInclusion <<-- Party. Now I need to define a persistent alias
Aircraft.CurrentOperator, which returns Party from currently valid
AircraftInclusion (for simplicity I assume only one instance of
AircraftInclusion per Aircraft in my examples below. I tired several variants
of Aircraft.CurrentOperator implementation resulting with different error
messages in XAF application.
C#[PersistentAlias("AircraftInclusions[].Single(Party)")]
public Party CurrentOperator
{
get { return EvaluateAlias("CurrentOperator") as Party; }
}
ERROR MESSAGE: The 'Party' property path is incorrect for the 'ELVAC.AIS.Model.FlightManagement.Aircraft' type because the 'ELVAC.AIS.Model.FlightManagement.Aircraft.Party' member does not exist
C#[PersistentAlias("[<AircraftInclusion>][^.Id = Aircraft.Id].Single(Party)")]
public Party CurrentOperator
{
get { return EvaluateAlias("CurrentOperator") as Party; }
}
ERROR MESSAGE: The 'Party' property path is incorrect for the 'ELVAC.AIS.Model.FlightManagement.Aircraft' type because the 'ELVAC.AIS.Model.FlightManagement.Aircraft.Party' member does not exist
How this could be? In this to case above I’m querying
explicitly defined AircraftInclusion type? The Party property used in argument
of Single function defines only what property from result (AircraftInclusion)
should by returned? Is it correct? (there is no documentation of Single
function at all, so I can only assume).
C#[PersistentAlias("Iif(CurrentAircraftInclusion IS NOT NULL, CurrentAircraftInclusion.Party, NULL)")]
public Party CurrentOperator
{
get { return EvaluateAlias("CurrentOperator") as Party; }
}
[PersistentAlias("AircraftInclusions[].Single()")]
public AircraftInclusion CurrentAircraftInclusion
{
get { return EvaluateAlias("CurrentAircraftInclusion") as AircraftInclusion; }
}
ERROR MESSAGE: Incorrect member 'CurrentOperator' in a path. A reference property or collection association is expected.
Thanks a lot for any advice, example or (in best case)
reference to documentation of Single function.
Hi Martin.
I am afraid the information you provided is insufficient to diagnose this issue. Note that a collection to which you are applying the Single aggregate should not contain more than one object in any event. Also refer to the Documentation - Improve documentation on the Single aggregate (add examples, describe limitations, etc.) article.
If this does not help, provide us with the source code of your persistent classes.
I extracted two typical scenarios I can’t make working in my application into example solution (in attachment). Try to run my app and sort or filter by persistent aliases OrganizationUnit.Boss and OrganizationUnit.BossAddress. It results into very unpleasant behavior.
Could you provide me with more detailed information regarding Single function usage. I tried almost everything but I can’t still make use of this. I investigated links your provided me with, but without any significant success.
I would also like to ask, if my examples of persistent alias I posted earlier are correct on formal side at least.
I’m currently dealing with more problems related to Single function, but I want to start with the simple ones first.
Thanks a lot.
This scenario has been discussed in ticket Single in PersistentAlias causes freeze when sorting (see the last comment).
>>>Could you provide me with more detailed information regarding Single function usage.
We will provide detailed documentation for the Single aggregate function in the future. Currently, you can only search the Support Center for known issues.
>>>I would also like to ask, if my examples of persistent alias I posted earlier are correct on formal side at least.
I cannot determine if criteria expressions you listed in the first post are valid without persistent class declarations.
1) I tried to replace Single function with the Max aggregate operation as described in ticket you provided me with, but with no success. The resulting error message is still the same.
2) Could you please provide me with THE MOST SIMPLE EXAMPLE POSSIBLE, where two classes with one-to-many relation are used and there will be persistent alias definition retrieving a single record from collection of associated objects (where more than one record in this collection can be contained). Please use my example I sent in my last post, where everything is prepared and all I ask is several letters to be modified from your side (the persistent alias expression). Thank a lot for your assistance, because this is a highly critical issue for our project.
Thanks a lot for your understanding and assistance.
First, if a company can have only one boss, you need add a unique index to enforce this rule at the database level and avoid exceptions with the Single function. To handle the situation when a company has no boss, the second property can be declared as follows:
[PersistentAlias("[<Person>][IsBoss AND not Address is null and ^.Oid = OrganizationUnit.Oid].Single(Address)")] public MyAddress BossAddress { get { return EvaluateAlias("BossAddress") as MyAddress; } }
I probably did not explained my request correctly. As I mentioned in previsous post [… retrieving a single record from collection of associated objects (where more than one record in this collection can be contained)], the Single function can't be used. Do I understand it correctly? (quoting Q457501: "You can use the Single aggregate only if a collection under no circumstances can return more than one row.")
If so, I would need to help with implementation of a different approach in my persistent aliasses, possibly with Max aggregation function or any different way. (not sure about exact solution).
I also noted, that this problem with my persistent aliasses does not relates to XAF application only. I just found out, that this exception rises also in case of XPQueries.
Could you please add a working example of such a persistent alias into solution I posted.
Sorry I'm bothering you so intensively, but it is really a critical issue for us in a high profile project which is about to release.
Thanks a lot for your help.
>>>Do I understand it correctly? (quoting Q457501: …)
Yes. You cannot use the Single aggregate in this scenario.
>>>If so, I would need to help with implementation of a different approach in my persistent aliasses…
Your requirements are too unclear to provide a solution. What behavior you expect from the Boss and BossAddress properties when there are more than one person marked as boss in a company.
>>>I also noted, that this problem with my persistent aliasses does not relates to XAF application only. I just found out, that this exception rises also in case of XPQueries.
This limitation is not specific to XAF. The Single function is a part of the Data Library and has an implementation in the XPO Library.
Thanks a lot for your response. I will try to make it more clear. I would need to be able to define a persistent alias, which retreives a single (or null) record from associated collection of persistent objects and does not results in thrown exception in any case (even in case there si more than one record available or any other cases).
Regarding to your question what do I need from persistent aliases:
- Boss is Person instance marked with IsPerson property == TRUE. By chance there can be more than one instance with IsPerson==TRUE. In such a case I would like to get let say the first one by Person.Name property (or choose different rule - it is just an example).
- BossAddress is Boss.Address in case when Boss IS NOT NULL.
Sorry I did not explained it more in detail earlier. I see this task as simple as possible, however I'm fighting this for a serveral days already :(.
Thanks a lot once again.
Thank you very much for the clarification. I am afraid it is impossible to create a persistent alias property with these capabilities. There are two possible alternatives:
[PersistentAlias("Persons[IsBoss].Max(Name)")] public string BossName { get { return Convert.ToString(EvaluateAlias("BossName")); } }
public Person Boss { get { return Session.FindObject<Person>(CriteriaOperator.Parse("OrganizationUnit=? and IsBoss", this)); } } public MyAddress BossAddress { get { return Boss == null ? null : Boss.Address; } }
I hope this helps.
Thank you for your explanation. Few conclusions just to make ti absolutely clear to me:
Could you please confirm this two conclusions?
I have also one additional question. When there is a typical implementation of getter with persistent alias using the EvaluateAlias method and Single method is used in the frame of this persistent alias expression, for instance like this:
[PersistentAlias("[<InfoPanelFlightRemarkTemplate>][InfoPanelFlightState = ^.InfoPanelFlightState].Single()")]
public InfoPanelFlightRemarkTemplate InfoPanelFlightRemarkTemplate
{
get { return EvaluateAlias("InfoPanelFlightRemarkTemplate") as InfoPanelFlightRemarkTemplate; }
}
…, and getter is called (it means EvaluateAlias method is also called), does this method evaluates expression also over in-memory instances (like InTransaction mode), or does it evaluate over objects currently stored in database?
Thanks a lot for your help.
I just found out, that it is possible to assure there will be never more than 1 record in our solution. In other words collection where a Single function is called will contain ONE or ZERO items (it means Single function would be usable). In such a case, how I have to modify my example to make it (my persistent aliases) working. Because even I manage to follow this rule, the example solution (attached earlier) results in exceptions I mentioned above. Just try to launch it an sort listview by persistent alias columns.
Could you modify my example to make this two simple persistent aliases working. This would definetely help us to make our project alive.
Thanks a lot
I have already provided a solution for this situation. Please review my comment #3 (click the "Show all comments" link to reveal it).
I just implemented the persistent alias exactly as you described in your comment #3, but it still results in this exception:
Property path 'Address' is incorrect for type 'ProblemWithSingleFunction.Module.BusinessObjects.OrganizationUnit' because member 'ProblemWithSingleFunction.Module.BusinessObjects.OrganizationUnit.Address' does not exist.
I tried also another variants of persistent alias implementations, but with no success at all. Could you please have a swift look at the new version of example solution I'm enclosing, which includes new variants and modify at least one of them to working one. That would be the most effective and also the fastest way how to solve this.
Thanks a lot in advance.
After removing incorrectly implemented BossAddressVariantBA and BossAddressVariantBB properties, I cannot reproduce any exception in your project. Property BossAddressVariantA is implemented correctly.
I can not agree. I did it again and attached screenshot.
Do I something different/wrong?
I cannot reproduce this issue on my side, sorry. See the attached video.
Note, I have tested your project with the latest release version (12.2.6) of our libraries. I you are using an older build, please update the DXpereince installation.