-
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
Add affected entries to "SavedChanges" callback #26564
Comments
I could override |
@douglasg14b Call context.SaveChanges(acceptAllChangesOnSuccess: false);
context.ChangeTracker.AcceptAllChanges(); This will cause the event to fire before all the entity states have been changed. Note for triage: it would be useful to have events for accepting changes to cover this. |
Gotcha, that makes sense then. Thanks! |
Related to #626 |
@douglasg14b I have the same use case as you, and the approach you mentioned above (get entity states, handle before, call SaveChanges, handle after) was the way I used to do it in "old" EF. The workaround mentioned above is very interesting. Did you do it that way? There could be a race condition where some other code (maybe the domain event handler) calls SaveChanges again before you call I'm trying to decide between these approaches:
|
For why there's no race condition (as mentioned above by @lonix1), see dotnet/EntityFramework.Docs#3645. |
Hey @douglasg14b, given roji's comments in that linked issue, my feeling now is that the |
@lonix1 I am not considering race conditions since each scope has it's own I am handling this with a SaveChanges override. This is what I've thrown together, it works thus far, but I'm sure isn't very elegant. I haven't actually tested the transaction yet, hopefully the setup doesn't have errors... public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
// We already started, and this is a savechanges call made after we have already entered this fuction
if(Database.CurrentTransaction != null) // <----- hack to capture nested savechanges calls
{
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
OnBeforeSaveChanges(); // <---- Does all the observe-ability stuff, and sets up necessary state
int result = 0;
using (var transaction = Database.BeginTransaction())
{
try
{
result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
IStatus afterSaveStatus = await OnAfterSavedChangesAsync(); // <---- Perform all the post-save changes actions, this can also call SaveChanges
if (afterSaveStatus.HasErrors) throw new Exception(afterSaveStatus.ToString()); // <--- Abort if errors
await transaction.CommitAsync();
}
catch (Exception ex)
{
// Log?
await transaction.RollbackAsync();
throw; // Rethrow the exception so callers can handle
}
}
return result;
}
|
@douglasg14b I like it. I used to do something very similar in an older EF version - I don't know why you think it's inelegant, it was the standard way for a long time. I assume you still need to use ajcvcker's |
Ask a question
I need to perform an action after modified entities are persisted, but am having a hard time figuring out how to determine if an entity was modified after the fact? It doesn't seem like the
SavedChanges
callback includes a list of modified/new/deleted entities.The specific use case is that I need to emit some domain events after changes have been persisted, but I don't know how to determine which entities where modified in the
SavedChanges
callback.This seems like something that falls under: #626 but I wanted to check if there was an already supported method of doing this.
Include provider and version information
EF Core version: 5
Target framework: NET 5.0
The text was updated successfully, but these errors were encountered: