2

Let's say I have the following classes: person, widget, foo_bars.

A person can have multiple widgets and foo_bars.

When an admin deletes a person, I want my code to do a cascading delete... and remove all related records in the database for this person In my widget class, I have a delete method... and the same is true for my foo_bars class

But in order to accomodate something like the person delete function, I feel like I should be creating "Person Manager" class, that will actually repeat a version all the logic inside both the delete methods in the widgets / foo_bars classes. (instead of just calling the existing methods on the classes.

Here's what I'm thinking:

Example 1

 public class PersonManager{

     delete_person(personID as int)
     { 
        // assume that I've queried for list of all widget and foobars IDs.
        //1.  delete all widgets for personID
        success = true
        dim obj_widget = new widget;
        loop through all widgets  
            result = obj_widget.delete(widgetID)   
            if not result then
               success = false 
               exit with error
            end if  
        end loop 

        //2.  delete all foo bars for personID
        if success then 
            dim objfoobar= new foo_bars;
            loop through all foobars
                result = objfoobar.delete(foobarid)    
                 if not result then
                    success = false
                    exit loop
                  end  
            end loop 
         end 

        //3. delete person record. 
        if success then 
             result = databaseobj.deleteperson(personID)
             if not result then 
                 return false, "Delete person failed because...."
             else
                 return true
             end                
        end 
     }
 }

In the above example, I'm trying to demo the reuse of existing the existing delete methods on each class... and then if it successfully deletes all widgets and foobars for the person, then i delete the person record itself.

The problem with this is that if the widgets delete properly, but the foo_bars don't, how do I rollback? Each delete method has it's own transaction defined within, because deleting a widget or foo bar involves, let's say 2 - 3 steps. So, in other words, the delete method on the widget class currently looks like this:

    public class widget{
         delete_widget{
                 database.execute("BEGIN TRANSACTION")
                 database.execute("DELETE FROM XYX ...")
                 if successful then 
                        database.execute("DELETE FROM yyy...")
                 else 
                        database.execute("ROLL BACK")
                        return false
                 end if
                 database.execute("COMMIT")
                 return true
              }
      }

For each widget, I'll be calling this method... So what if all the widgets delete, but it dies deleting the first foobar? I think I have to rewrite the code to delete everything right inside the Person manager class and wrap it in a transaction, instead of calling the existing delete methods on the classes. At least, that's what I'm thinking. If there's another way to look at this problem, please let me know. I could just write a cascading delete SQL statement in the PersonManager class, and not call the methods on the two classes. But I don't know if using SQL cascading deletes is a good thing... Thanks!

4
  • I think the need for function to be inside some manager to be able to use transaction is wrong. There should be no problem using transaction and only commiting if everything is success.
    – Euphoric
    Dec 27 '13 at 21:41
  • Euphoric, I've just clarified my post.
    – dot
    Dec 27 '13 at 21:44
  • Can you just wrap the top-level parent delete in a transaction and remove the individual transactions on the child elements?
    – Bobwise
    Dec 27 '13 at 21:49
  • that's also an interesting suggestion @Bobwise. I'll give it some more thought.
    – dot
    Dec 30 '13 at 16:49
1

So your problem are nested transactions. I think this could be solved by separating the transaction logic from the data logic.

Something like Command pattern, where commands represent the operations and the one executing the command is in charge of transactions is good fit. You could even nicely compose the commands of various deletes. And even the ugly success testing and setting could be nicely encoded in some specific composite command that handles the success logic.

1
  • hmm... i'll take a look
    – dot
    Dec 27 '13 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.