如何用EntityFrameworkCore.Triggered定义自定义触发器类型?事务触发器完整教程
如何用EntityFrameworkCore.Triggered定义自定义触发器类型事务触发器完整教程【免费下载链接】EntityFrameworkCore.TriggeredTriggers for EFCore. Respond to changes in your DbContext before and after they are committed to the database.项目地址: https://gitcode.com/gh_mirrors/en/EntityFrameworkCore.TriggeredEntityFrameworkCore.Triggered是一款为 EF Core 提供数据库触发器能力的开源库让你可以在DbContext的数据保存之前或提交之后自动执行自定义逻辑。本文将带你以**事务触发器Transactional Triggers**为例掌握定义自定义触发器类型的完整方法只需 3 步即可扩展出属于自己的触发时机。一、快速认识 EntityFrameworkCore.Triggered想象这样一个场景每当SaveChanges被调用时你希望自动给新注册的学生发送欢迎邮件、打上时间戳或在数据落库后同步缓存。EntityFrameworkCore.Triggered就是为这类响应式数据处理而生的。它默认提供了 3 种内置触发器类型触发器接口执行时机IBeforeSaveTriggerTEntitySaveChanges 提交之前IAfterSaveTriggerTEntitySaveChanges 成功之后IAfterSaveFailedTriggerTEntity保存抛出异常之后这 3 种类型能覆盖大多数场景。但当你需要更精细的控制——比如在数据库事务提交之前做最后一道检查或事务回滚之后发送告警——就需要定义自定义触发器类型了。二、为什么需要自定义触发器类型很多数据库如 SQL Server默认会把每次SaveChanges包裹在一个事务里但触发器的before/after save并不等于before/after commitBeforeSave里的修改包含在事务内回滚会一并撤销AfterSave里的修改在事务外执行即便事务失败这些操作也可能已经发生。如果你要手动控制事务BeginTransaction/Commit/Rollback就需要 4 个新的触发时机IBeforeCommitTrigger、IAfterCommitTrigger、IBeforeRollbackTrigger、IAfterRollbackTrigger官方正是用这套事务触发器扩展包来演示如何定义自定义触发器类型的代码位于src/EntityFrameworkCore.Triggered.Transactions目录下面我们就把它拆开看。三、定义自定义触发器类型的 3 个步骤步骤 1定义触发器接口为每一种触发时机定义一个泛型接口接收ITriggerContextTEntity上下文。以最简单的IBeforeCommitTrigger为例public interface IBeforeCommitTriggerin TEntity where TEntity : class { void BeforeCommit(ITriggerContextTEntity context); }该接口定义在src/EntityFrameworkCore.Triggered.Transactions.Abstractions/IBeforeCommitTrigger.cs。注意两点接口只依赖抽象层EntityFrameworkCore.Triggered.Abstractions不依赖 EF Core 本身这样扩展包更轻量、更易维护使用in TEntity协变约束让实现可以接收基类型的触发器上下文天然支持继承。步骤 2编写 Raise 扩展方法触发器需要一个开关来在合适的时机被调用。官方为ITriggerSession编写了一系列扩展方法位于src/EntityFrameworkCore.Triggered.Transactions/TriggeredSessionExtensions.cspublic static void RaiseBeforeCommitTriggers(this ITriggerSession triggerSession) { // 1. 使用不级联的发现策略避免循环触发 var strategy new NonCascadingTriggerContextDiscoveryStrategy(BeforeCommit); // 2. 告诉 TriggerSession去查找 IBeforeCommitTrigger 类型的触发器 // 并为每个实体类型创建对应的描述符Descriptor ((TriggerSession)triggerSession).RaiseTriggers( typeof(IBeforeCommitTrigger), null, strategy, entityType new BeforeCommitTriggerDescriptor(entityType)); }这里的两个关键组件值得新手记住发现策略DiscoveryStrategy决定如何扫描 DbContext 中待处理的变更。事务触发器使用NonCascadingTriggerContextDiscoveryStrategy即不做级联——提交前不应该再引发新一轮变更触发器描述符TriggerTypeDescriptor通过反射把触发器类型 实体类型绑定成一个可快速调用的委托见src/EntityFrameworkCore.Triggered.Transactions/Internal/BeforeCommitTriggerDescriptor.cs。同理该文件还实现了RaiseAfterCommitTriggers、RaiseBeforeRollbackTriggers、RaiseAfterRollbackTriggers等全部 8 个入口同步 异步各 4 个命名规律一目了然扩展方法对应触发器接口RaiseBeforeCommitTriggers()IBeforeCommitTriggerTRaiseAfterCommitTriggers()IAfterCommitTriggerTRaiseBeforeRollbackTriggers()IBeforeRollbackTriggerTRaiseAfterRollbackTriggers()IAfterRollbackTriggerT步骤 3注册并调用你的触发器使用方只需安装EntityFrameworkCore.Triggered.Transactions包在配置中启用事务触发器并注册实现类services.AddDbContextApplicationDbContext(options { options.UseTriggers(triggerOptions { triggerOptions.UseTransactionTriggers(); // 启用事务触发器 triggerOptions.AddTriggerLogBeforeCommitTrigger(); // 注册你的实现 }); });在业务代码中手动控制事务并触发对应时机using var tx context.Database.BeginTransaction(); var triggerSession context.GetServiceITriggerService().CreateSession(context); try { await context.SaveChangesAsync(); await triggerSession.RaiseBeforeCommitTriggers(); // ✅ 提交前 await tx.CommitAsync(); await triggerSession.RaiseAfterCommitTriggers(); // ✅ 提交后 } catch { await triggerSession.RaiseBeforeRollbackTriggers(); // ✅ 回滚前 await tx.RollbackAsync(); await triggerSession.RaiseAfterRollbackTriggers(); // ✅ 回滚后 throw; }四、事务触发器的完整生命周期除了按实体触发BeforeCommit(ITriggerContextTEntity)扩展包还提供了Lifecycle 生命周期触发器位于src/EntityFrameworkCore.Triggered.Transactions.Abstractions/Lifecycles/每次触发周期只执行一次适合做日志汇总、指标上报IBeforeCommitStartingTrigger/IBeforeCommitCompletedTriggerIAfterCommitStartingTrigger/IAfterCommitCompletedTrigger一次完整的事务触发时序如下SaveChanges→ 触发 BeforeSave / AfterSave 触发器事务提交前 →BeforeCommitStarting→ 各实体BeforeCommit→BeforeCommitCompletedCommit之后 →AfterCommitStarting→ 各实体AfterCommit→AfterCommitCompleted若发生异常则依次执行BeforeRollback→ 回滚 →AfterRollback链路五、新手最佳实践清单接口放 Abstractions实现放主包模仿EntityFrameworkCore.Triggered.Transactions.Abstractions与EntityFrameworkCore.Triggered.Transactions的分离方式保持扩展包零 EF Core 依赖⚙️善用配置入口参考TriggerOptionssrc/EntityFrameworkCore.Triggered/TriggerOptions.cs的模式为你的自定义触发器提供UseXxxTriggers()风格的链式配置按需选择级联策略修改实体的触发器用默认的EntityAndType级联策略只读型触发器如事务触发器用NoCascade防止无限循环⚡同时提供同步 异步版本事务触发器每个时机都提供RaiseXxxTriggers与RaiseXxxAsyncTriggers建议照做以兼容不同调用场景为每个 Raise 方法写集成测试可参考test/EntityFrameworkCore.Triggered.Transactions.Tests/TriggeredDbContextTests.cs中的写法——先SaveChanges再调用RaiseBeforeCommitTriggers()断言触发器被调用了正确的次数。六、总结通过本文你已经掌握了用EntityFrameworkCore.Triggered定义自定义触发器类型的完整套路并以事务触发器为例走通了全流程定义接口在 Abstractions 层为每种触发时机声明泛型接口编写 Raise 扩展方法配合发现策略与触发器描述符把触发器接入ITriggerSession注册并调用用户通过UseTriggers配置启用在事务各阶段显式触发。这套模式完全可以复用到任何你需要的触发时机——无论是发布前校验、审计归档还是缓存失效。动手试试吧你的 EF Core 项目也可以拥有独一无二的触发器生态【免费下载链接】EntityFrameworkCore.TriggeredTriggers for EFCore. Respond to changes in your DbContext before and after they are committed to the database.项目地址: https://gitcode.com/gh_mirrors/en/EntityFrameworkCore.Triggered创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考