You're right that use of the EntityChanging event to handle cascaded deletions falls short when asynchronous navigation is involved. One workaround, when possible, is to pre-load the dependent objects so you avoid this situation altogether. When that's not possible, we really don't have a great answer for this right now.
I did look at using the AsyncSerialTask to do this and came up with something which works, but is a bit ugly. Pending entity resolution is not currently handled the same way as other asynchronous actions within DevForce, but we will look at making this easier. The sample below takes advantage of how the AsyncSerialTask passes arguments and results from step to step.
AsyncSerialTask.Create<Customer>("DeleteCustomer")
.AddAsyncAction<AsyncEventArgs>(SetupDeletion)
.AddAction(args => DoDelete((Customer)args.UserState))
.Execute(aCustomerToBeDeleted);
// "callback" is called when entities are available
// the Customer is passed as the userState to the AsyncEventArgs
private void SetupDeletion(Customer cust, AsyncCompletedCallback<AsyncEventArgs> callback) {
var list = cust.OrderSummaries;
bool isPending = list.IsPendingEntityList;
if (isPending) {
list.PendingEntityListResolved += (o, args) => {
callback(new AsyncEventArgs(cust));
};
} else {
callback(new AsyncEventArgs(cust));
}
}
// Called by AsyncSerialTask when the prior step completes.
private void DoDelete(Customer cust) {
cust.EntityAspect.Delete();
foreach (var order in cust.OrderSummaries.ToList()) {
order.EntityAspect.Delete();
}
}