Remove Entity Then Delete, During a save action an entity's update action failed. The entity which failed is enclosed.

Posts   
 
    
mprothme avatar
mprothme
User
Posts: 78
Joined: 05-Oct-2017
# Posted on: 27-May-2020 23:45:03   

Build Version: 5.5 (5.5.0) RTM, Build Date: 02-Nov-2018 Project: Adapter project targetting .NET 4.5.2 Database: MS Sql on 2016

We have a Table called CalculatedValue, and a child table called CalculatedValueVariable used to model formulas. The variable table has a nullable FK to Calculated Value. In our application users can modify the formula and individual variables and then click Save. On save, synchronization logic fires that does standard create/update/delete logic. When a variable is removed the following happens:

1) The entity is removed from entity Collection on its parent CalculatedValue record. Each deleted record is placed in an entity collection called deletedVars. 2) Adapter.deleteEntityCollection is called on deletedVars 3) Adapter.Save is called on the parent CalculatedValue record, with refetch and recurse set to true. We're leveraging recurse here to save any new/updated Variable entities.

Looking through other posts, it seems like this error can happen when an update effects zero records in the database. I did a SQL trace and it looks like the following SQL runs when I delete a single variable on an existing CalculatedValue and update the formula string to remove the now-deleted variable.

1) A Delete for the variable we deleted 2) An Update for the CalculatedValue record 3) An update query targeting the deleted variable which attempts to set the FK that points to their parent CalculatedValue record to null

In this case, the second update returns zero results because the variable records were already deleted.

Any tips for getting around this or is there a better way to do what we're doing? I know I could save the parent record recursively first, and then delete the child records after and reload the record, but that seems counterintuitive.

mprothme avatar
mprothme
User
Posts: 78
Joined: 05-Oct-2017
# Posted on: 28-May-2020 05:13:34   

Update: If we don't call remove at all on the entity collection, instead just adding the entity to our deletedVars collection, we can then call delete on the variable entity and save the parent afterward it all seems to work.

Is this by design?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 28-May-2020 07:14:44   

All your tests work as expected. I would better make changes in the graph, then save the parent recursively, after all it seems to be the principal object in this case. Or, update first, delete later.

In scenarios where multiple dependent actions take place, you also could use UnitOfWork. This is how it works: you add actions to a UnitOfWork, then commit the work. The actions took place into a Transaction and in this order: inserts, updates, deletes. You also could modify this order and write pre/post actions. When you need some sort of flexibility or the process is long and you would rather commit at the end of a process, you could add actions to a UnitOfWork.

Hope that helps simple_smile

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 28-May-2020 10:50:44   

Checking what the code does, it does check on EntityState.Deleted for an entity that's passed in to SaveEntity() but it's not doing that when it recurses over a graph and finds a dirty entity that also has been deleted.

So we acknowledge this is a flaw in our system (as it shouldn't add entities that are marked as deleted to an update queue) and we'll correct this in a future version.

What you can try is to call CalculatedValueVariable.DetachFromGraph() on the CalculatedValueVariable entities that get deleted (so right before they're placed in the collection to delete). This detaches them from the graph and they won't be visited when the graph is traversed for entities to persist.

Frans Bouma | Lead developer LLBLGen Pro
mprothme avatar
mprothme
User
Posts: 78
Joined: 05-Oct-2017
# Posted on: 28-May-2020 20:21:23   

Thanks for your answers!

I'll give DetachFromGraph a try just to see, but I think for now it's simplest for us to just not call .Remove in this case (the in-memory variables themselves aren't actually accessed after the save)