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?