Child_DeleteSelf not being calledChild_DeleteSelf not being called
Old forum URL: forums.lhotka.net/forums/t/5693.aspx
RandyH posted on Wednesday, October 29, 2008
I have code that looks similar to the following:
Public Class Parent
Inherits BusinessBase(Of Parent)
Private Shared MyChildListProperty As PropertyInfo(Of ChildList) = RegisterProperty(Of ChildList)(GetType(Child), New PropertyInfo(Of ChildList)("MyChildList", "The Child List"))
Public ReadOnly Property MyChildList() As ChildList
Get
Return GetProperty(Of ChildList)(MyChildListProperty)
End Get
End Property
....
Private Overloads Sub DataPortal_Delete(ByVal criteria As Object)
'-- delete from db
FieldManager.UpdateChildren(criteria)
End Sub
....
End Class
Public Class ChildList
Inherits BusinessListBase(Of ChildList, Child)
....
End Class
Public Class Child
Inherits BusinessBase(Of Child)
....
Private Sub Child_DeleteSelf(ByVal criteria As Object)
'delete from db
End Sub
....
End Class
When I call parent.Delete (parent is an instance) the parent object is being deleted from the db. But the children are not marked as dirty or isdeleted and so the Child_DeleteSelf is not being called. I seem to be missing something that marks the children for delete. Any help would be greatly appreciated.
JoeFallon1 replied on Wednesday, October 29, 2008
The basic concept you are missing is that you have to manage the entire delete yourself from within the Parent class.
You are incorrectly relying on CSLA to delete the child objects for you in this case.
In database terms you are looking to do a Cascade Delete.
What the ChildList does in CSLA is give you a way to delete individual rows from a child table when a user "edits" them in the UI and marks them for deletion.
If the Parent is deleted and you want all the child rows to be removed too then you have to handle it yourself.
Something like this:
Protected
Overrides Sub DataPortal_DeleteSelf()
DataPortal_Delete(New CriteriaCode(GetType(Item), "DataPortal_DeleteSelf", mItemno))
End Sub
Protected Overrides Sub DataPortal_Delete(ByVal criteria As Object)
Dim strSQL As String
Dim crit As CriteriaCode = DirectCast(criteria, CriteriaCode)
strSQL = ItemDAO.Delete(crit.Code)
Dim tr As IDbTransaction = Nothing
Try
tr = Me.BeginTransaction()
'Delete child objects before deleting the parent.
DeleteChildren(tr, criteria)
'delete the parent
DAL.ExecuteNonQuery(tr, CommandType.Text, strSQL)
PostDeleteData(tr, user)
Me.EndTransaction(tr)
Catch ex As Exception
Me.RollbackTransaction(tr)
Throw
End Try
End Sub
Protected Overridable Sub DeleteChildren(ByVal tr As IDbTransaction, ByVal criteria As Object)
Dim crit As CriteriaCode = DirectCast(criteria, CriteriaCode)
DAL.ExecuteNonQuery(tr, CommandType.Text, ItemchildDAO.DeleteByItemno(crit.Code))
End Sub
Joe
RandyH replied on Wednesday, October 29, 2008
I now have a solution that seems to work.
In the parent class I now have this code
Public Overrides Sub Delete()
Me.ChildList.Clear()
MyBase.Delete()
End Sub
The clear marks the children for delete. Then the FieldManager.UpdateChildren call in the parent.DataPortal_Delete will then make the calls to the Child_DeleteSelf in each of the children.
Any problems with this solution?
tetranz replied on Wednesday, October 29, 2008
I think the more efficient thing to do is simply to get your stored procedure or whatever your DAL uses to delete the child records directly when it deletes the parent.
My parent_delete sproc usually does something like this:
DELETE FROM ChildTable
WHERE ParentId = @Id
DELETE FROM ParentTable
WHERE Id = @Id
eulerthegrape replied on Wednesday, October 29, 2008
I use this solution too and it works perfectly until you create a foreign key relationship between parent and child table and don't perform the deletion in the order described by tetranz...
ajj3085 replied on Wednesday, October 29, 2008
True, but that's fairly easy to find and fix when it happens.
JoeFallon1 replied on Wednesday, October 29, 2008
The drawback to your solution is that if there are 500 child rows in the collection then you will send 500 queries to the DB to remove them one at a time.
My solution and the SP offered by tetranz only send 2 queries in total.
Joe
ajj3085 replied on Thursday, October 30, 2008
Well, I wasn't advocating one solution over another... just pointing out the "problem" of order was a pretty trivial one because it's easy to find and easy to fix.
Of course it's not the number of queries that matter, its how many queries you send at once over the network. If you're using L2S it will submit your changes in a single batch when you call SubmitChanges. Many queries, but just one network hop. Performance should be fine.
JoeFallon1 replied on Thursday, October 30, 2008
FYI the "your solution" in my comment was to RandyH - the op who originally posted and the re-posted his solution. I was not referring to Andy's comments at all.
Joe
ajj3085 replied on Thursday, October 30, 2008
Ahh... I thought you were replying to me from the post numbers.
eulerthegrape replied on Thursday, October 30, 2008
I was merely relating my first time "experience." Once you've seen this "problem," yes it is a trivial fix but it was a head scratcher for me the first time. If it saves some one some heartburn I think it's a valid "gotcha" to point out.
Copyright (c) Marimer LLC