You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Convert README to reflect the AutoGuru-maintained fork targeting .NET 9 / EF Core 9. Update package names, NuGet badges and links to use AutoGuru.* packages and the autoguru-au GitHub org. Clarify trigger invocation (ISaveChangesInterceptor), update transaction/extension package links, fix various sample code formatting/typos, and add an acknowledgement noting the project is a fork of koenbeuk/EntityFrameworkCore.Triggered.
Copy file name to clipboardExpand all lines: README.md
+40-37Lines changed: 40 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,44 +1,44 @@
1
-
# EntityFrameworkCore.Triggered 👿
1
+
# EntityFrameworkCore.Triggered
2
2
Triggers for EF Core. Respond to changes in your DbContext before and after they are committed to the database.
3
3
4
-
[](https://www.nuget.org/packages/EntityFrameworkCore.Triggered/)
This is the [AutoGuru](https://github.com/autoguru-au)-maintained fork, targeting .NET 9 / EF Core 9. Published as `AutoGuru.*` NuGet packages.
5
+
6
+
[](https://www.nuget.org/packages/AutoGuru.EntityFrameworkCore.Triggered/)
1. Install the package from [NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Triggered)
17
+
1. Install the package from [NuGet](https://www.nuget.org/packages/AutoGuru.EntityFrameworkCore.Triggered)
16
18
2. Write triggers by implementing `IBeforeSaveTrigger<TEntity>` and `IAfterSaveTrigger<TEntity>`
17
19
3. Register your triggers with your DbContext
18
-
4. View our [samples](https://github.com/koenbeuk/EntityFrameworkCore.Triggered/tree/master/samples) and [more samples](https://github.com/koenbeuk/EntityFrameworkCore.Triggered.Samples) and [a sample application](https://github.com/koenbeuk/EntityFrameworkCore.BookStoreSampleApp)
19
-
5. Check out our [wiki](https://github.com/koenbeuk/EntityFrameworkCore.Triggered/wiki) for tips and tricks on getting started and being successful.
20
-
21
-
> Since EntityFrameworkCore.Triggered 2.0, triggers will be invoked automatically, however this requires EF Core 5.0. If you're stuck with EF Core 3.1 then you can use [EntityFrameworkCore.Triggered V1](https://www.nuget.org/packages/EntityFrameworkCore.Triggered/1.4.0). This requires you to inherit from `TriggeredDbContext` or handle manual management of trigger sessions.
5. Check out our [wiki](https://github.com/autoguru-au/EntityFrameworkCore.Triggered/wiki) for tips and tricks on getting started and being successful.
22
22
23
-
> [EntityFrameworkCore.Triggered V3](https://www.nuget.org/packages/EntityFrameworkCore.Triggered/3.0.0) is now available for those targeting EF Core 6 or later
23
+
> This fork targets .NET 9 / EF Core 9. Triggers are invoked automatically via EF Core's `ISaveChangesInterceptor`.
[Youtube presentation](https://youtu.be/Gjys0Yebobk?t=671) - Interview by the EF Core team
106
106
107
107
### Trigger discovery
108
-
In the given example, we register triggers directly with our DbContext. This is the recommended approach starting from version 2.3 and 1.4 respectively. If you're on an older version then it's recommended to register triggers with your application's DI container instead:
108
+
In the given example, we register triggers directly with our DbContext. This is the recommended approach. If you prefer, you can register triggers with your application's DI container instead:
109
109
110
110
```csharp
111
111
services
@@ -115,7 +115,7 @@ In the given example, we register triggers directly with our DbContext. This is
115
115
116
116
Doing so will make sure that your triggers can use other services registered in your DI container.
117
117
118
-
You can also use functionality in [EntityFrameworkCore.Triggered.Extensions](https://www.nuget.org/packages/EntityFrameworkCore.Triggered.Extensions/) which allows you to discover triggers that are part of an assembly:
118
+
You can also use functionality in [AutoGuru.EntityFrameworkCore.Triggered.Extensions](https://www.nuget.org/packages/AutoGuru.EntityFrameworkCore.Triggered.Extensions/) which allows you to discover triggers that are part of an assembly:
In this example, triggers will be executed in the order:
154
-
* those for `IAnimal`,
153
+
In this example, triggers will be executed in the order:
154
+
* those for `IAnimal`,
155
155
* those for `Animal`
156
-
* those for `ICat`, and finally
157
-
*`Cat` itself.
156
+
* those for `ICat`, and finally
157
+
*`Cat` itself.
158
158
159
159
If multiple triggers are registered for the same type, they will execute in order they were registered with the DI container.
160
160
161
161
### Priorities
162
162
In addition to inheritance and the order in which triggers are registered, a trigger can also implement the `ITriggerPriority` interface. This allows a trigger to configure a custom priority (default: 0). Triggers will then be executed in order of their priority (lower goes first). This means that a trigger for `Cat` can execute before a trigger for `Animal`, for as long as its priority is set to run earlier. A convenient set of priorities are exposed in the `CommonTriggerPriority` class.
163
163
164
164
### Error handling
165
-
In some cases, you want to be triggered when a `DbUpdateException` occurs. For this purpose we have `IAfterSaveFailedTrigger<TEntity>`. This gets triggered for all entities as part of the change set when DbContext.SaveChanges raises a DbUpdateException. The handling method: `AfterSaveFailed` in turn gets called with the trigger context containing the entity as well as the exception. You may attempt to call `DbContext.SaveChanges` again from within this trigger. This will not raise triggers that are already raised and only raise triggers that have since become relevant (based on the cascading configuration).
165
+
In some cases, you want to be triggered when a `DbUpdateException` occurs. For this purpose we have `IAfterSaveFailedTrigger<TEntity>`. This gets triggered for all entities as part of the change set when DbContext.SaveChanges raises a DbUpdateException. The handling method: `AfterSaveFailed` in turn gets called with the trigger context containing the entity as well as the exception. You may attempt to call `DbContext.SaveChanges` again from within this trigger. This will not raise triggers that are already raised and only raise triggers that have since become relevant (based on the cascading configuration).
166
166
167
167
### Lifecycle triggers
168
168
Starting with version 2.1.0, we added support for "Lifecycle triggers". These triggers are invoked once per trigger type per `SaveChanges` lifecyle and reside within the `EntityFrameworkCore.Triggered.Lifecycles` namespace. These can be used to run something before/after all individual triggers have run. Consider the following example:
Console.WriteLine($"We've sent {_emailAddresses.Count()} emails to {_emailAddresses.Distinct().Count()}"distinctemailaddresses");
183
183
returnTask.CompletedTask;
@@ -186,7 +186,7 @@ public BulkReportTrigger : IAfterSaveTrigger<Email>, IAfterSaveCompletedTrigger
186
186
```
187
187
188
188
### Transactions
189
-
ManydatabaseproviderssupporttheconceptofaTransaction. BydefaultwhenusingSqlServerwithEntityFrameworkCore, anycallto `SaveChanges` willbewrappedinatransaction. Anychangesmadein `IBeforeSaveTrigger<TEntity>` willbeincludedwithinthetransactionandchangesmadein `IAfterSaveTrigger<TEntity>` willnot. However, itispossiblefortheuserto [explicitlycontroltransactions](https://docs.microsoft.com/en-us/ef/core/saving/transactions). Triggers are extensible and one such extension are [Transactional Triggers](https://www.nuget.org/packages/EntityFrameworkCore.Triggered.Transactions/). In order to use this plugin you will have to implement a few steps:
189
+
ManydatabaseproviderssupporttheconceptofaTransaction. BydefaultwhenusingSqlServerwithEntityFrameworkCore, anycallto `SaveChanges` willbewrappedinatransaction. Anychangesmadein `IBeforeSaveTrigger<TEntity>` willbeincludedwithinthetransactionandchangesmadein `IAfterSaveTrigger<TEntity>` willnot. However, itispossiblefortheuserto [explicitlycontroltransactions](https://docs.microsoft.com/en-us/ef/core/saving/transactions). Triggers are extensible and one such extension are [Transactional Triggers](https://www.nuget.org/packages/AutoGuru.EntityFrameworkCore.Triggered.Transactions/). In order to use this plugin you will have to implement a few steps:
190
190
```csharp
191
191
// OPTIONAL: Enable transactions when configuring triggers (Required ONLY when not using dependency injection)
192
192
triggerOptions.UseTransactionTriggers();
@@ -197,25 +197,28 @@ var triggerSession = triggerService.CreateSession(context); // A trigger session
Bydefaultweoffer3triggertypes: `IBeforeSaveTrigger`, `IAfterSaveTrigger` and `IAfterSaveFailedTrigger`. Thesewillcovermostcases. Inadditionweoffer `IRaiseBeforeCommitTrigger` and `IRaiseAfterCommitTrigger` asanextensiontofurtherenhanceyourcontrolofwhentriggersshouldrun. Wealsooffersupportforcustomtriggers. Let's say we want to react to specific events happening in your context. We can do so by creating a new interface `IThisThingJustHappenedTrigger` and implementing an extension method for `ITriggerSession` to invoke triggers of that type. Please take a look at how [Transactional triggers](https://github.com/koenbeuk/EntityFrameworkCore.Triggered/tree/master/src/EntityFrameworkCore.Triggered.Transactions) are implemented as an example.
214
+
Bydefaultweoffer3triggertypes: `IBeforeSaveTrigger`, `IAfterSaveTrigger` and `IAfterSaveFailedTrigger`. Thesewillcovermostcases. Inadditionweoffer `IRaiseBeforeCommitTrigger` and `IRaiseAfterCommitTrigger` asanextensiontofurtherenhanceyourcontrolofwhentriggersshouldrun. Wealsooffersupportforcustomtriggers. Let's say we want to react to specific events happening in your context. We can do so by creating a new interface `IThisThingJustHappenedTrigger` and implementing an extension method for `ITriggerSession` to invoke triggers of that type. Please take a look at how [Transactional triggers](https://github.com/autoguru-au/EntityFrameworkCore.Triggered/tree/master/src/EntityFrameworkCore.Triggered.Transactions) are implemented as an example.
215
215
216
216
### Async triggers
217
-
Asynctriggersarefullysupported, thoughyoushouldbeawarethatiftheyarefiredasaresultofacalltothesynchronous `SaveChanges` onyourDbContext, thetriggerswillbeinvokedandtheresultswaitedforbyblockingthecallerthreadasdiscussed [here](https://github.com/koenbeuk/EntityFrameworkCore.Triggered/issues/127). This is known as the sync-over-async problem which can result in deadlocks. It's recommended to use `SaveChangesAsync` to avoid the potential for deadlocks, which is also best practice anyway for an operation that involves network/file access as is the case with an EF Core read/write to the database.
217
+
Asynctriggersarefullysupported, thoughyoushouldbeawarethatiftheyarefiredasaresultofacalltothesynchronous `SaveChanges` onyourDbContext, thetriggerswillbeinvokedandtheresultswaitedforbyblockingthecallerthreadasdiscussed [here](https://github.com/autoguru-au/EntityFrameworkCore.Triggered/issues/127). This is known as the sync-over-async problem which can result in deadlocks. It's recommended to use `SaveChangesAsync` to avoid the potential for deadlocks, which is also best practice anyway for an operation that involves network/file access as is the case with an EF Core read/write to the database.
218
218
219
219
### Similar products
220
220
- [Ramses](https://github.com/JValck/Ramses): Lifecycle hooks for EF Core. A simple yet effective way of reacting to changes. Great for situations where you simply want to make sure that a property is set before saving to the database. Limited though in features as there is no dependency injection, no async support, no extensibility model and lifecycle hooks need to be implemented on the entity type itself.
221
221
- [EntityFramework.Triggers](https://github.com/NickStrupat/EntityFramework.Triggers). Add triggers to your entities with insert, update, and delete events. There are three events for each: before, after, and upon failure. A fine alternative to EntityFrameworkCore.Triggered. It has been around for some time and has support for EF6 and boast a decent community. There are plenty of trigger types to opt into including the option to cancel SaveChanges from within a trigger. A big drawback however is that it does not support cascading triggers so that triggers can never be relied on to enforce a domain constraint.
222
+
223
+
## Acknowledgements
224
+
Thisprojectisaforkof [EntityFrameworkCore.Triggered](https://github.com/koenbeuk/EntityFrameworkCore.Triggered) originally created by [koenbeuk](https://github.com/koenbeuk). Thank you for the excellent foundation.
0 commit comments