Кажется, это правильный способ сделать это, за исключением, возможно, того факта, что в catch вы должны перебросить исключение или сделать что-то еще, чтобы остановить прогресс в цикле (если я правильно понял ваши требования). Даже не нужно использовать
var transaction = context.Database.BeginTransaction()
потому что
await context.SaveChangesAsync();
создает собственную транзакцию. Каждое внесенное вами изменение сохраняется в контексте, и когда вы вызываете SaveChanges, происходит транзакция, и все изменения записываются как 1 пакет. Если что-то не получается, все изменения отменяются. Еще один вызов SaveChanges совершит еще одну транзакцию при новых изменениях. Однако имейте в виду, что в случае сбоя транзакции вам больше не следует использовать тот же контекст, а создавать новый. Подводя итог, я бы написал ваш метод следующим образом:
private async Task ProcessCollectionsAsync(DbContext context, IList<Order> ordersToCollect)
{
if (ordersToCollect.Count == 0) return;
Log.Debug($"ProcessCollections: processing {ordersToCollect.Count} orders");
foreach (var order in ordersToCollect)
{
// group the 3 operations in one transaction for each order
// so that if one operation fails, the operations performend on the previous orders
// are committed
try
{
// *************************
// run the 3 operations here
// operations consist of updating the order itself, and other database updates
Operation1(order);
Operation2(order);
Operation3(order);
// *************************
await context.SaveChangesAsync();
}
catch (Exception ex)
{
Log.Error("General exception when executing ProcessCollectionsAsync on Order " + order.Id, ex);
throw;
}
}