Search code examples
c#entity-frameworktransactionstransactionscope

Is a TransactionScope appropriate to include side effects in the Entity Framework transaction?


Imagine the following operation using Entity Framework 6:

// operations on some entities

// send an email
// write to a file

db.SaveChanges();

If db.SaveChanges(); fails, the email shouldn't be delivered, and the file shouldn't be written to. Am I correct in understanding that I would need to wrap all the code in a TransactionScope to achieve this behaviour? Like so:

using(var transaction = new TransactionScope())
{
    // operations on entities here

    // send an email
    // write to a file

    db.SaveChanges();
    transaction.Complete();
}

Solution

  • No, because you have problems:

    • Email is not transnational. So you CAN handle this by writing a Compensating Resource Manager that only sends the email on commit - with a new API. But if you send the email via SMTP it is sent - the mail server will not care about your transaction.
    • File - well, transcriptional NTFS is officially retired ;) But you could use that. A CRM (Compensating Resource Manager) and a file backup at begin could handle this though.

    So, generally - that approach is valid, but your two cases are really bad.

    In this particular case I would likely use separate queued business transactions controlled via SQL Broker (or MSMQ) to start the other 2 operations once the commit is done.