新生自动报名所有必修课:EntityFrameworkCore.Triggered级联触发器实战演示
2026/8/22 15:52:21 网站建设 项目流程

新生自动报名所有必修课: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.Triggered

EntityFrameworkCore.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 时加一个UseTriggers

options.UseInMemoryDatabase("PrimarySchool") .UseTriggers(triggerOptions => { triggerOptions.AddTrigger<Triggers.StudentSignupToMandatoryCourses>(); });

注册完成后,程序往数据库里添加了两门课程(必修的数学、选修的美术),然后添加了一名叫 Joe 的学生并调用SaveChanges。最终控制台输出:

Joe is registered for course Mathematics

Joe 被自动报上了必修课——这就是我们接下来要看的核心机制。✨

三、触发器代码解读:自动报名是怎么发生的?

自动报名的全部逻辑都在samples/2 - PrimarySchool/Triggers/StudentSignupToMandatoryCourses.cs里,它实现了IBeforeSaveAsyncTrigger<Student>接口,意思是"Student 实体保存前,先执行我"。

它做了三件事:

  1. 查询出所有IsMandatory == true的必修课
  2. 逐个检查当前学生是否已经报名(StudentCourses.Find
  3. 没有报名的课程,就往 DbContext 里追加一条StudentCourse记录

关键在于第 3 步:触发器是在SaveChanges真正写库之前执行的,此时往 DbContext 追加的新实体会被一起提交。换句话说,你保存 1 个学生,数据库里却写入了 1 个学生 + N 条选课记录,浑然一体。💪

四、级联是如何工作的:EntityAndType 级联策略

这里就引出了标题中的主角——级联(Cascading)

在 Before 触发器里往 DbContext 追加了新实体后,库会重新扫描变更集。如果新实体也有注册的触发器,这些触发器同样会被触发,就像多米诺骨牌一样层层传递。

但级联必须防止死循环(A 触发 B,B 又触发 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(根节点),结果:

  1. 删除最深层节点 → 该节点被软删除 ✅
  2. 删除第 2 层节点 → 第 2 层 + 第 3 层都被软删除 ✅
  3. 删除根节点 → 3 级全部被软删除 ✅

一次删除,级联触发器顺着父→子的引用把整条链都"软删除"了。这种"保存即生效"的级联能力,正是 EntityFrameworkCore.Triggered 最实用的特性之一。🌳

五、如何为你的项目快速接入?

三步完成集成:

第 1 步:安装 NuGet 包

在项目中安装EntityFrameworkCore.Triggered包即可(纯接口包EntityFrameworkCore.Triggered.Abstractions可单独引用)。

第 2 步:编写触发器

实现IBeforeSaveTrigger<TEntity>(同步)或IBeforeSaveAsyncTrigger<TEntity>(异步)接口,在方法里通过context.Entity拿到实体、通过context.ChangeType判断是新增还是修改。参考samples/1 - HelloWorld/Triggers/StudentAssignRegistrationDate.cs,它仅用几行代码就实现了"新增学生时自动填写注册日期"。

第 3 步:注册触发器

UseTriggers中逐个AddTrigger即可;如果项目里触发器较多,还可以用EntityFrameworkCore.Triggered.Extensions包提供的方法对整个程序集批量扫描注册。

💡 小贴士:使用异步触发器时,请配合SaveChangesAsync调用,避免同步调用异步导致的线程阻塞问题(官方 README 中有专门说明)。

想亲手跑一遍本文示例?克隆仓库后进入示例目录执行dotnet run

git 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询