Removing All References to Unsaved Entities

Posts   
 
    
mprothme avatar
mprothme
User
Posts: 78
Joined: 05-Oct-2017
# Posted on: 06-Oct-2017 17:49:47   

We have a contract entry application that allows users to create, update, and delete entities through a web UI. After a user finishes his/her edits and clicks save, their entry is validated against a set of business rules. If all entities pass validation the structure is saved to the database, if not then the user has to make changes. These entities form a one to many parent-child relationships similar to below. With each entity having navigators, or entity collections, between each other.

Parent Entity - 1:m - Detail Entity - 1:m sub-item.

Additionally, all of the items have foreign keys (and navigators) to reference data tables, with many of the items having keys to the same table. For example, Parent, Detail, and sub-item have foreign keys and navigators to Location and Currency tables.

We’re seeing an issue where if a sub item or detail item is removed by calling .Remove() from its parent entity’s collection, the item still persists in memory. When we call adapter.save with recursive set to true, the sub-item still gets saved. We’ve also tried additionally setting the navigator from the child item to the parent item to null, but we still get the same problem.

From reading other posts, my guess is that when we save recursively, the saves may be going through some of the reference data entities (for example if parent and detail point to the same location entity) and are thus able to arrive at the child record we attempted to remove.

My question then is three parts:

  • If a parent and child item both reference the same entity from a third table, would a recursive save from the parent reach the child through said reference entity, even if the parent and child didn’t directly reference each other (I’m guessing the answer to this is yes, but I wanted to do my due diligence).
  • If I want to remove an unsaved item completely from the object graph (so that it would not be saved), what are the steps I need to take. Can I simply set all navigators pointing out from the child item to null? Or do I also need to find any entity collections it may have been a part of and remove it from those as well?
  • Is there potentially some kind of remove all references method that would take care of some of this for me? or a way to do this generically? There are a significant number of reference tables, and maintaining a procedure that cleaned up references as we add or remove reference data tables is something I would prefer to avoid if I could.

Thanks in advance!

Matt

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Oct-2017 07:51:53   

mprothme wrote:

If a parent and child item both reference the same entity from a third table, would a recursive save from the parent reach the child through said reference entity, even if the parent and child didn’t directly reference each other (I’m guessing the answer to this is yes, but I wanted to do my due diligence).

Yes, in a recursive save this would be true, if those two objects (say X and Y) reference the same object O.

mprothme wrote:

If I want to remove an unsaved item completely from the object graph (so that it would not be saved), what are the steps I need to take. Can I simply set all navigators pointing out from the child item to null? Or do I also need to find any entity collections it may have been a part of and remove it from those as well?

You should set their navigators to null, so LLBLGen framework would run the de-sync routine .

mprothme wrote:

Is there potentially some kind of remove all references method that would take care of some of this for me? or a way to do this generically? There are a significant number of reference tables, and maintaining a procedure that cleaned up references as we add or remove reference data tables is something I would prefer to avoid if I could.

AFAIK: no. There is not a general routine for this. However you could write your own general routine that explores all references of an object and set them to null.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 09-Oct-2017 10:12:52   

You could have a look at DataScope, which does contain a method (it's private, see the sourcecode of DataScopeContext, 'RemoveSubGraphFromMainGraph', in the runtime libraries sourcecode in the sourcecode archive available on the website) for this and runs it automatically. It also tracks removed entities for you and builds a unit of work if you need one.

http://www.llblgen.com/Documentation/5.2/LLBLGen%20Pro%20RTF/Using%20the%20generated%20code/gencode_datascopes.htm

DataScopes are designed for databinding purposes, but you don't have to use them for that, they're general purpose classes which can take care of the management of graphs in-memory for you.

Frans Bouma | Lead developer LLBLGen Pro
mprothme avatar
mprothme
User
Posts: 78
Joined: 05-Oct-2017
# Posted on: 10-Nov-2017 23:35:06   

Thanks for the replies, we ended up using reflection to identify any entity type properties on an object and set them to null, something like the following:


        private void DereferenceEntity(IEntity2 entityToDereference)
        {
            var entityType = typeof(IEntity2);
            var properties = entityToDereference.GetAllPropertiesImplementingInterface(entityType);
            foreach (KeyValuePair<PropertyInfo, object> keyValuePair in properties)
            {
                keyValuePair.Key.SetValue(entityToDereference, null);
            }
        }

where GetAllPropertiesImplementingInterface returns property info records for all properties on an object implementing the interface.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 11-Nov-2017 09:53:05   
Frans Bouma | Lead developer LLBLGen Pro