Ticket T285117
Visible to All Users

NonPersistentObjectSpace - Support showing persistent objects in non-persistent objects' Views

created 10 years ago (modified 9 years ago)

Scenario:

  1. A list of non-persistent objects should be shown in a dashboard, and one of the columns should contain a persistent object - T284048.
  2. It is necessary to assign an employee to several tasks. A user should select tasks, click a button, and a dialog with the selected tasks and the employees lookup should be shown - T179848.
  3. It is necessary to show a non-persistent popup dialog with a persistent Card lookup and a non-persistent CardElements list - T214493.
  4. It is necessary to show a dialog allowing you to select a persistent object in a lookup - see T362128T106536.

Issues:

  1. It is necessary to load the initial values for referenced persistent objects. They cannot be loaded through the View's ObjectSpace, since NonPersistentObjectSpace cannot load persistent objects.
  2. Certain controllers may work incorrectly with persistent references, since NonPersistentObjectSpace provides unexpected information for them (e.g., it does not return a key value). As a reference, see Application.CreateCollectionSource and Application.CreateListView throws "type is non-persistent" when invoked on NonPersistentObjectSpace.

Current Solutions:
It is possible to implement simple solutions for each particular scenario and more complicated generic solutions here. For instance, in scenario #4, you can consider using the approach from the How to show a non-persistent class DetailView and filter related persistent lookup editors dynamically article, which relies on a persistent IObjectSpace and an orphan non-persistent class instantiated without any parameters. If necessary, you can always pass a required IObjectSpace object or other external data into this non-persistent class to implement a more complicated logic.

An example of a generic solution would be an attempt to implement a NonPersistentObjectSpace descendant that internally uses a persistent IObjectSpace instance for operations with persistent objects:

C#
public class MixedObjectSpace : NonPersistentObjectSpace { IObjectSpace persistentObjectSpace; public MixedObjectSpace(ITypesInfo typesInfo, IObjectSpace persistentObjectSpace) : base(typesInfo) { this.persistentObjectSpace = persistentObjectSpace; } public MixedObjectSpace(ITypesInfo typesInfo, IEntityStore entityStore, IObjectSpace persistentObjectSpace) : base(typesInfo, entityStore) { this.persistentObjectSpace = persistentObjectSpace; } public override object GetKeyValue(object obj) { Guard.ArgumentNotNull(obj, "obj"); if (persistentObjectSpace.CanInstantiate(obj.GetType())) { return persistentObjectSpace.GetKeyValue(obj); } else { return base.GetKeyValue(obj); } } public override string GetKeyValueAsString(object obj) { Guard.ArgumentNotNull(obj, "obj"); if (persistentObjectSpace.CanInstantiate(obj.GetType())) { return persistentObjectSpace.GetKeyValueAsString(obj); } else { return base.GetKeyValueAsString(obj); } } public override object FindObject(Type objectType, DevExpress.Data.Filtering.CriteriaOperator criteria, bool inTransaction) { if (persistentObjectSpace.CanInstantiate(objectType)) { return persistentObjectSpace.FindObject(objectType, criteria, inTransaction); } else { return base.FindObject(objectType, criteria, inTransaction); } } public override object CreateObject(Type type) { if (persistentObjectSpace.CanInstantiate(type)) { return persistentObjectSpace.CreateObject(type); } else { return base.CreateObject(type); } }     public override IList CreateCollection(Type objectType, CriteriaOperator criteria, IList<SortProperty> sorting) {         if (persistentObjectSpace.CanInstantiate(objectType)) {             return persistentObjectSpace.CreateCollection(objectType, criteria, sorting);         } else {             return base.CreateCollection(objectType, criteria, sorting);         }     }     public override object GetObjectKey(Type objectType, string objectKeyString) {         if (persistentObjectSpace.CanInstantiate(objectType)) {             return persistentObjectSpace.GetObjectKey(objectType, objectKeyString);         } else {             return base.GetObjectKey(objectType, objectKeyString);         }     }     public override object GetObjectByKey(Type type, object key) {         if (persistentObjectSpace.CanInstantiate(type)) {             return persistentObjectSpace.GetObjectByKey(type, key);         } else {             return base.GetObjectByKey(type, key);         }     } ... } public class MixedObjectSpaceProvider : NonPersistentObjectSpaceProvider, IObjectSpaceProvider { private IObjectSpaceProvider persistentObjectSpaceProvider; public MixedObjectSpaceProvider(ITypesInfo typesInfo, NonPersistentEntityStore entityStore, IObjectSpaceProvider persistentObjectSpaceProvider) : base(typesInfo, entityStore) { this.persistentObjectSpaceProvider = persistentObjectSpaceProvider; } IObjectSpace IObjectSpaceProvider.CreateObjectSpace() { return new MixedObjectSpace(TypesInfo, EntityStore, persistentObjectSpaceProvider.CreateObjectSpace()); } }
Show previous comments (6)
Dennis Garavsky (DevExpress) 9 years ago

    @Volkan: Please submit a separate ticket with a small debuggable sample reproducing this behavior so we can research it. Thanks.

    VA VA
    Volkan Alkılıç 1 9 years ago

      Hi Dennis,
      I found the problem. Problem occurs when the following code activated;
      DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.Enable(DevExpress.ExpressApp.Security.Adapters.ReloadPermissionStrategy.OnLogon);

      Dennis Garavsky (DevExpress) 9 years ago

        Hello Volkan,

        To process your recent post more efficiently, I created a separate ticket on your behalf: T296849: ArgumentNullException can occur when DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.Enable is used. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

        Answers approved by DevExpress Support

        created 9 years ago

        We have implemented the functionality described in this ticket. It will be included in our next update(s).

        Please check back and leave a comment to this response to let us know whether or not this solution addresses your concerns.

        Additional information:

        We have added the AdditionalObjectSpaces collection to the NonPersistentObjectSpace class. This collection may contain Object Spaces required to handle persistent objects you are going to display in non-persistent objects' views. For instance, consider the following non-persistent class exposing the reference property of a persistent type.

        C#
        using DevExpress.ExpressApp.DC; using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl; // ... [DomainComponent, DefaultClassOptions] public class NonPersistentObject { // ... public string Name { get; set; } public Person Owner { get; set; } // ... }

        By default, the NonPersistentObject Detail View  displays the lookup editor for the Owner property, but the lookup is empty and you cannot choose any existing Person.


        The reason is that the NonPersistentObjectSpace Object Space created for the current View cannot handle the Person persistent object. So, you should create an additional Object Space for the Person type and add it to the NonPersistentObjectSpace.AdditionalObjectSpaces collection. The following WindowController illustrates this.

        C#
        using DevExpress.ExpressApp; using DevExpress.Persistent.BaseImpl; // ... public class AdditionalPersonObjectSpaceController : WindowController { public AdditionalPersonObjectSpaceController() : base() { TargetWindowType = WindowType.Main; } private IObjectSpace additionalObjectSpace; protected override void OnActivated() { base.OnActivated(); Application.ObjectSpaceCreated += Application_ObjectSpaceCreated; additionalObjectSpace = Application.CreateObjectSpace(typeof(Person)); } protected override void OnDeactivated() { base.OnDeactivated(); Application.ObjectSpaceCreated -= Application_ObjectSpaceCreated; if (additionalObjectSpace != null) { additionalObjectSpace.Dispose(); additionalObjectSpace = null; } } private void Application_ObjectSpaceCreated(Object sender, ObjectSpaceCreatedEventArgs e) { if (e.ObjectSpace is NonPersistentObjectSpace) { ((NonPersistentObjectSpace)e.ObjectSpace).AdditionalObjectSpaces.Add(additionalObjectSpace); } } }

        The result is demonstrated below.

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.