NickStrupat / EntityFramework.Triggers

Adds events for entity inserting, inserted, updating, updated, deleting, and deleted
MIT License
373 stars 46 forks source link

EF.Triggers and .Net Core transactions #49

Open chicobaptista opened 4 years ago

chicobaptista commented 4 years ago

Hello I've a question about using your EF.Triggers library together with Transactions and transactions scopes.

We're using transactions when modifying several database entries, so that if one operation fails/ is rejected, the whole transaction rolls back. However, since there are multiple context.SaveChanges() calls inside the transactions, the Triggers.Updated and .TriggersInserted triggers are activated, and if the transaction is rolled back, I have not found a way to revert the changes made by the handlers when the triggers are activated. I am mostly using the library to send the database changes to a realtime subset database, and this library would be a nice way to keep this second db in sync.

Reading other issues (specifically https://github.com/NickStrupat/EntityFramework.Triggers/issues/20#issuecomment-339540426_) and questions on SO and googling, I found some references that Triggers.Updated or Triggers.Created should be used only when you know that the data has been persisted.

Is there a trigger that gets activated on rollback (Triggers.UpdateFailed and such don't appear to behave this way) or any other suggestion on how to handle this situation? One of our options includes rewriting the whole transactions logic to make just one context.SaveChanges() call per transaction, accumulating all EF changes in one batch, but that would have other implications to our architecture and frankly would mean a lot of rewriting, so if possible I would like to avoid that as much as possible.

NickStrupat commented 4 years ago

Hi @chicobaptista ,

Hi @chicobaptista ,

This is an interesting use case. I hadn't come up with a good design for handling transactions so I just left it.

Could you create a transaction for the other context and roll it back if the first one throws?

chicobaptista commented 4 years ago

Hey @NickStrupat, we don't actually have different db contexts, but multiple .Savechanges() calls in the same context, but this approach of using another transaction that catches and rollbacks on a throw might be something to look further.

We came up with another idea today, to use the Transaction.Current.TransactionInformation.LocalIdentifier property to batch together events emmited by EF.Triggers on a single transaction and then emitting a different event (through an extension of TransactionScope) on TransactionScope.Complete() or TransactionScope.Dispose() to fire our desired handler, since this way we know if the data has been persisted or rolled back. Should work, and maybe we could PR this implementation into the library, if you think it interesting to do so.

NickStrupat commented 4 years ago

So the transaction isn't applied to all the changes within that single instance of DbContext?