新生自动报名所有必修课:EntityFrameworkCore.Triggered级联触发器实战演示

发布时间:2026/8/22 15:52:44
新生自动报名所有必修课: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 打造的触发器Trigger扩展库它让你可以在实体写入数据库之前或之后自动执行业务逻辑。今天我们就用它的官方小学示例实战演示当一个新生被添加到数据库时如何借助级联触发器自动完成所有必修课的报名而你的业务代码一行都不用写。一、为什么需要 EF Core 触发器想象这样一个场景每新增一名学生系统都要确保他报名了所有必修课。没有触发器时这段逻辑通常散落在各种 Service、Controller 里很容易漏掉某个入口比如批量导入、API 调用。EntityFrameworkCore.Triggered 的思路是把业务规则绑定到实体上而不是绑到调用入口上。只要你对DbContext调用了SaveChanges与实体相关的触发器就会被自动执行无论这次保存来自哪个功能模块。核心能力一览⚡Before 触发器在数据落库前执行可以直接修改实体或往 DbContext 里追加新实体After 触发器在数据落库后执行适合发通知、记日志级联触发器Before 触发器里新增的实体还能继续触发它们自己的触发器错误触发器SaveChanges抛出异常时执行IAfterSaveFailedTrigger做善后二、官方示例PrimarySchool 里的自动报名项目自带了一个非常直观的示例位于samples/2 - PrimarySchool/目录我们直接拆解它。数据模型学生、课程、选课记录samples/2 - PrimarySchool/ApplicationDbContext.cs中定义了三个实体实体作用Student学生含学号、姓名、注册日期Course课程含IsMandatory标记是否为必修课StudentCourse学生与课程的关联表以学生Id、课程Id为复合主键注册触发器一行 UseTriggers 搞定在samples/2 - PrimarySchool/Program.cs中整个集成只需要在配置 DbContext 时加一个UseTriggersoptions.UseInMemoryDatabase(PrimarySchool) .UseTriggers(triggerOptions { triggerOptions.AddTriggerTriggers.StudentSignupToMandatoryCourses(); });注册完成后程序往数据库里添加了两门课程必修的数学、选修的美术然后添加了一名叫 Joe 的学生并调用SaveChanges。最终控制台输出Joe is registered for course MathematicsJoe 被自动报上了必修课——这就是我们接下来要看的核心机制。✨三、触发器代码解读自动报名是怎么发生的自动报名的全部逻辑都在samples/2 - PrimarySchool/Triggers/StudentSignupToMandatoryCourses.cs里它实现了IBeforeSaveAsyncTriggerStudent接口意思是Student 实体保存前先执行我。它做了三件事查询出所有IsMandatory true的必修课逐个检查当前学生是否已经报名StudentCourses.Find没有报名的课程就往 DbContext 里追加一条StudentCourse记录关键在于第 3 步触发器是在SaveChanges真正写库之前执行的此时往 DbContext 追加的新实体会被一起提交。换句话说你保存 1 个学生数据库里却写入了 1 个学生 N 条选课记录浑然一体。四、级联是如何工作的EntityAndType 级联策略这里就引出了标题中的主角——级联Cascading。在 Before 触发器里往 DbContext 追加了新实体后库会重新扫描变更集。如果新实体也有注册的触发器这些触发器同样会被触发就像多米诺骨牌一样层层传递。但级联必须防止死循环A 触发 BB 又触发 A。库默认采用EntityAndType级联策略同一个实体 同一种变更类型新增/修改/删除只触发一次从而天然杜绝了无限循环。相关源码可以参考级联行为定义src/EntityFrameworkCore.Triggered/Infrastructure/CascadeBehavior.cs级联策略实现src/EntityFrameworkCore.Triggered/Internal/CascadeStrategies/核心调度器src/EntityFrameworkCore.Triggered/TriggerSession.cs一个更震撼的级联场景多层级软删除集成测试test/EntityFrameworkCore.Triggered.IntegrationTests/CascadingSoftDeletes/演示了一个多层级联树形结构 3 级分支每级都注册了软删除触发器。此时只调用Remove(根节点)结果删除最深层节点 → 该节点被软删除 ✅删除第 2 层节点 → 第 2 层 第 3 层都被软删除 ✅删除根节点 → 3 级全部被软删除 ✅一次删除级联触发器顺着父→子的引用把整条链都软删除了。这种保存即生效的级联能力正是 EntityFrameworkCore.Triggered 最实用的特性之一。五、如何为你的项目快速接入三步完成集成第 1 步安装 NuGet 包在项目中安装EntityFrameworkCore.Triggered包即可纯接口包EntityFrameworkCore.Triggered.Abstractions可单独引用。第 2 步编写触发器实现IBeforeSaveTriggerTEntity同步或IBeforeSaveAsyncTriggerTEntity异步接口在方法里通过context.Entity拿到实体、通过context.ChangeType判断是新增还是修改。参考samples/1 - HelloWorld/Triggers/StudentAssignRegistrationDate.cs它仅用几行代码就实现了新增学生时自动填写注册日期。第 3 步注册触发器在UseTriggers中逐个AddTrigger即可如果项目里触发器较多还可以用EntityFrameworkCore.Triggered.Extensions包提供的方法对整个程序集批量扫描注册。 小贴士使用异步触发器时请配合SaveChangesAsync调用避免同步调用异步导致的线程阻塞问题官方 README 中有专门说明。想亲手跑一遍本文示例克隆仓库后进入示例目录执行dotnet rungit clone https://gitcode.com/gh_mirrors/en/EntityFrameworkCore.Triggered cd EntityFrameworkCore.Triggered/samples/2\ -\ PrimarySchool dotnet run六、进阶能力速览学完基础后这些特性值得了解详见项目根目录的README.md执行优先级实现ITriggerPriority接口可自定义同一实体的多个触发器执行顺序CommonTriggerPriorities提供了一组常用预设值继承支持触发器按从抽象类型到具体类型的顺序执行基类触发器先跑子类后跑事务触发器EntityFrameworkCore.Triggered.Transactions扩展包支持在提交前/提交后、回滚前/回滚后各挂触发器覆盖完整的数据库事务生命周期生命周期触发器Lifecycles命名空间下提供AfterSaveCompleted等钩子在本次保存的所有触发器都执行完后统一执行一次适合做批量汇总统计总结EntityFrameworkCore.Triggered 把数据变更后的业务规则从散乱的业务代码中抽离出来统一挂载到DbContext的保存流程上。通过本文的 PrimarySchool 示例我们看到了它的核心价值用Before 触发器在写库前自动补全数据新生自动报名必修课靠EntityAndType 级联策略让触发器安全地层层传递不陷入死循环配合异步接口与事务扩展能覆盖从简单记账到复杂事务的绝大多数场景如果你正在用 EF Core 管理 .NET 项目不妨从samples/目录的四个示例入手你会发现触发器真的能让数据维护这件事变得自动化。【免费下载链接】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),仅供参考