This is a bit of a poser, and I hope you'll find this challenging problem as interesting as I do... :)
I have a subclass of DataContext called MyDataContext, wherein I have overridden the SubmitChanges() method with some code of the form:
BeginTransaction(); // my own implementation
IList<object> Updates = GetChangeSet().Updates;
foreach (object obj in Updates) {
MyClass mc = obj as MyClass;
if (mc != null)
mc.BeforeUpdate(); // virtual method in MyClass to allow pre-save processing
}
// This is followed by similar code for the Deletes and Inserts, then:
base.SubmitChanges();
// Then do post-save processing...
foreach (object obj in Updates) {
MyClass mc = obj as MyClass;
if (mc != null)
mc.AfterUpdate(); // virtual method in MyClass to allow post-save processing
}
// similar code for Inserts and Deletes
// ...
CommitTransaction();
// obviously all enclosed in a try-catch block where the catch does a rollback
So far, so good. But there's a little problem, which surfaces if an implementation of MyClass invokes SubmitChanges() in its BeforeUpdate() or AfterUpdate() method. Now we have a recursion that is liable to lead to a stack overflow.
One way I thought of to work around this is to have a recursion-blocking variable at the beginning of SubmitChanges(). But what to do if the save is blocked? I can't spin it off into a new thread; the calling thread may require the SubmitChanges() call to be synchronous, e.g. if it needs access to an auto-number property immediately after the save.
An additional factor to consider is that if any objects are changed during the course of the pre- or post-processing, I also want their BeforeSave() and AfterSave() methods to be called.
Is there some clever textbook way of doing this all neatly and properly?