-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to save AuditEvent entities in the same transaction? #35345
Comments
If so I'd request an api to create a fresh instance of DbContext from the existing one. |
You can call |
When is it not the case?
|
Also, isn't it the risk of accepting changes prematurely? If the commit fails, the change tracker will be in a broken state so to say. |
shouldn't make a big difference, as if a transaction fails anywhere in the middle, you're forced to grab a fresh DbContext anyways, as the state it's currently in may be broken. This is why you retry outside of EF Code, e.g. in the controller level, and not in the "repository" level, if that makes sense. |
True, but this solves the issue of broken context. |
@kirides is right here, you're best off placing retrying your entire unit of work - on a fresh DbContext - from the start; this means that any error triggers restarting the previous context and state. This is also exactly who EF's retrying strategies generally work. |
Any reason you're using SavedChanges and not SavingChanges, which I think is supposed to run before the transaction is committed? |
AFAIK, |
Well, yes - SavingChanges is saved before changes are saved to the database, so obviously database-generated values aren't set at that point (the INSERT hasn't occured yet). But if your audit entities reference the things they audit, they'll have a foreign key which will get set by SavingChanges as usual (exactly like when you save a Blog and its Posts). If you don't want to do that, you'll need a separate SaveChanges to save your audit entities - you can trigger that from the SavedChanges interceptor (and make sure to not have that run on the second, auditing SaveChanges, e.g. via an async local), or simply by overriding the SaveChanges() method itself. |
I tried it first, but |
As to FKs on events. I let events to be as generic as possible:
It's the whole adventure to capture
|
If there's no user-managed transaction, that's probably the case (haven't checked). If you're looking to do things with two separate SaveChanges() - which is what I'm understanding - you'll need to manage transactions on your own, at which point you're in control exactly when the transaction is committed etc. In any case, is there any additional open question here? |
Is it safe to do it inside interceptor's code? Start transaction in |
@voroninp I'm not sure, starting a transaction in SavingChanges might be problematic (and of course would fail if you do have a user transaction already). I really recommend doing the simple thing and work with an explicit user transaction, rather than trying to automate things like this via interceptors; you can write generic code to take care of that for you - take a look at these docs, which are about resiliency, but are similar in spirit to what you're trying to achieve (i.e. close a unit of work in a single (retriable) block, which also gets automatically wrapped by a transaction). I'll go ahead and close this as I think the alternatives are clear and there's nothing actionable on the EF side, but if you still feel you need guidance you can continue posting. |
I want to create audit events using
ChangeTracker
.These events must be saved in the same transaction with the changed (added, modified, deleted) entities.
Current values of the properties must be read after they were generated (including the values generated in db).
I generate audit events in
TransactionCommittingAsync
method ofDbTransactionIntepceptor
. (transaction is started implicitly)The problem I face is that state of saved entities is not updated at the moment interceptor is called, and when I attach audit events and call
SaveChanges
oneventData.Context
entities get persisted second time.Should I inject
DbContextFactory
in my interceptor, create a new instance, enlist it in the same transaction, and then attach audit events to that instance?The text was updated successfully, but these errors were encountered: