-
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
Implement events for before and after SaveChanges #15910
Comments
For my main use case: A query level cache, it looks like I'd need an event after SaveChanges. The query level cache we used for EF6 was based on this project: https://github.com/moozzyk/EFCache Basically EFCache is using a custom DBCommand to figure out which entity sets are affected during Save/Rollback. It only needs to invalidate every cache entry of the specific entity set, so that's all the information it needs. The invalidation is done via If the new
See also this comment by the author of EFCache: #5858 (comment) |
@nphmuller Thanks for the info. I've also been doing some experiments with database interceptors, similar to EF6, which might be a better fit for this. |
My use case for this would be logging and audit trails. |
@ajcvickers Could we please have this for 3.1 (along with it's counterpart in #15911) |
@SidShetye We haven't decided what will be in 3.1 yet. |
@ajcvickers I would like to contribute this, it would be great if you provide more implementation details. |
Removing to discuss in triage: would an interceptor or normal events be better here? |
For us, the normal event is what is required. |
@SARAVANA1501 We discussed this in triage and agreed that the interceptor is most appropriate. This will allow Writing events to fire when the interceptor fires should be trivial. If not, we could revisit simple events as well. |
@ajcvickers , Will take a look |
@ajcvickers will it serve the purpose? |
@SARAVANA1501 It should more closely follow the pattern for other interceptors, including appropriate use of event data classes, sync/async overloads, interception results, etc. Off the top of my head something like this: public class SaveChangesEventData : DbContextEventData
{
public SaveChangesEventData(
EventDefinitionBase eventDefinition,
Func<EventDefinitionBase, EventData, string> messageGenerator,
DbContext context,
IList<IUpdateEntry> entriesToSave,
bool acceptChangesEnabled)
: base(eventDefinition, messageGenerator, context)
{
// TODO
}
}
public interface ISaveChangesInterceptor : IInterceptor
{
InterceptionResult<int> SavingChanges(
SaveChangesEventData eventData,
InterceptionResult<int> result);
Task<InterceptionResult<int>> SavingChangesAsync(
SaveChangesEventData eventData,
InterceptionResult<int> result,
CancellationToken cancellationToken = default);
int SavedChanges(
SaveChangesCompletedEventData eventData,
int result);
Task<int> SavedChangesAsync(
SaveChangesCompletedEventData eventData,
int result,
CancellationToken cancellationToken = default);
void SavingChangesFiled(
SaveChangesFailedEventData eventData);
} |
@ajcvickers Taking one step back, based off this,
what's the difference between the interceptors and events? Just a class vs a function or something more conceptually different? We've historically registered on the events, not interceptors, so that's our familiar go-to. The proposal above at face value seems like it may cover what we're looking for by wrapping our events into an interceptor class. (BTW How would one register the interceptor with EF? I guess it'll be very clear once this is implemented and there is a code sample demonstrating it's usage in documentation. @SARAVANA1501 Thanks for picking this up. Do you think it'll make it to the EF Core 3.1 release? |
Pretty sure it’s been mentioned that 3.1 will basically be only bug fixes. |
@ajcvickers Did you get chance to look at the above code? I am waiting for your comments to continue with other test cases. |
@SARAVANA1501 Sorry for being slow here. I think it might help if I provide a details on how an interceptor is intended to work:
The best way to get this all right is to thoroughly understand some of the existing interceptors and repeat the pattern here. For example, |
With no recent motion here would anyone object to me picking this up? |
Fixes #15910 I realized that the interceptor, while powerful, is hard to attach to without changing the context configuration. Therefore, this PR adds simple .NET events that can easily be attached to from outside the code that defines the context. Also, fix to call the SaveChanges failed interceptor when the failure is an optimistic concurrency exception.
Fixes #15910 I realized that the interceptor, while powerful, is hard to attach to without changing the context configuration. Therefore, this PR adds simple .NET events that can easily be attached to from outside the code that defines the context. Also, fix to call the SaveChanges failed interceptor when the failure is an optimistic concurrency exception.
Fixes #15910 I realized that the interceptor, while powerful, is hard to attach to without changing the context configuration. Therefore, this PR adds simple .NET events that can easily be attached to from outside the code that defines the context. Also, fix to call the SaveChanges failed interceptor when the failure is an optimistic concurrency exception.
Splitting this out as a separate issue as required on #626 so we can track it independently of other life-cycle hooks.
The text was updated successfully, but these errors were encountered: