Orphan Child Objects on Immediate Deletion

Orphan Child Objects on Immediate Deletion

Old forum URL: forums.lhotka.net/forums/t/4232.aspx


TheSquirrelKing posted on Thursday, January 24, 2008

Hi Rocky,

I've run into some unexpected behaviour using version 2.1.2 of the framework when it comes to deleting a parent class using immediate deletion. Assuming that 'Project' is my parent class, calling Project.DeleteProject and feeding in the relevant ID causes the Project object to be deleted as expected but is leaving orphaned child objects in the database. However, this is not the case when I delete a project using deferred deletion (by calling projectInstance.Delete() and then projectInstance.Save()).

This seems to be happening because DeleteProject, like the other factory methods, is Shared and therefore does not have access to the instance values of the object being deleted. So, when my DeleteChildren() method (called immediately within DataPortal_Delete)

Private Sub DeleteChildren()

   For Each item As Child In Children

      item.DeleteSelf()

   Next

End Sub

queries the exposed Project property

Public ReadOnly Property Children() As ChildCollection

   Get

      CanReadProperty(True)

      If _children Is Nothing Then

         _children = ChildCollection.GetChildCollection(_Id)

      End If

      Return _children

   End Get

End Property

to know which instances of the child object to call item.DeleteSelf() on, _children will always return an empty collection because _Id is empty instead of corresponding to the Project Id in question. I'm thinking I could fix this by altering DeleteChildren to look like this:

Private Sub DeleteChildren(ByVal parentID As Guid)

   For Each item As Child In ChildCollection.GetChildCollection(parentID)

      item.DeleteSelf()

   Next

End Sub

That said, I'm still wondering if this is intentional because both this behaviour and my workaround seem somewhat inconsistent with the style and structure of the rest of the framework.

ajj3085 replied on Thursday, January 24, 2008

I would think this is a bug in the example.   Try looking at the 3.0.3 version, as that's the most current for .Net 2 and see if it still behaves the same way.

TheSquirrelKing replied on Friday, January 25, 2008

We're not using the ProjectTracker when we're getting this behaviour, if that's what you mean - though I probably should set that up and see if it exhibits the same orphaning. And as far as using a more updated version of the framework, I really wish could but, for the moment, that's not happening (long story, circumstances beyond my control).

I would really appreciate it if anyone had any additional insight to share regarding this behaviour. As I said before, it seems pretty inconsistent and I'm trying to get a picture of how this might affect other aspects of this project.

Thanks.

ajj3085 replied on Friday, January 25, 2008

Well, I would check the PTracker example and see if its a problem there.  If it is, it could be a bug.  If not, its you're code.  Smile [:)]

Regarding upgrading... does it help an argument to upgrade to know that the 2.x line is officially depreciated, and won't be getting bug fixes anymore?

JoeFallon1 replied on Friday, January 25, 2008

When I code gen a BO the output for the Delete looks like this:

Protected Overrides Sub DataPortal_DeleteSelf()
  DataPortal_Delete(
New CriteriaKey(GetType(SomeBO), "DataPortal_DeleteSelf", mKey))
End Sub

Protected Overrides Sub DataPortal_Delete(ByVal criteria As Object)
  
Dim strSQL As String

  Dim crit As CriteriaKey = DirectCast(criteria, CriteriaKey)
  strSQL = SomeSQLClass.Delete(crit.Key)

  '
Transaction code removed for clarity.

  'Delete child objects before deleting the parent. 
 
DeleteChildren(tr, criteria)

 
'delete the parent
 
DAL.ExecuteNonQuery(tr, CommandType.Text, strSQL)
End Sub

Protected Overridable Sub DeleteChildren(ByVal tr As IDbTransaction, ByVal criteria As Object)
 
'marker method that can be overridden in child class
End Sub

===================================================================================

The key is that you have to be able to delete all the child records in the Database using only the passed in Criteria parameter(s). In this case the crit.Key value.

So you need to Override DeleteChildren and handle it yourself. Without using any Instance variables (as there are none!)

Protected Overrides Sub DeleteChildren(ByVal tr As IDbTransaction, ByVal criteria As Object)
  Dim crit As CriteriaKey = DirectCast(criteria, CriteriaKey)

  'delete Child Table1 records
 
DAL.ExecuteNonQuery(tr, CommandType.Text, Table1SQL.DeleteByKey(crit.Key))

  'delete Child Table2 records
 
DAL.ExecuteNonQuery(tr, CommandType.Text, Table2SQL.DeleteByKey(crit.Key))
End Sub

 

Joe

 

Copyright (c) Marimer LLC