关于 aurelius-objects
aurelius-objects 是面向 Delphi 开发者的 TMS Aurelius 对象持久化操作指南,说明如何通过 TObjectManager 查询、保存、更新和删除实体。内容还强调对象所有权、事务及关联处理规则。
主要功能
- 01通过 TObjectManager 管理持久化
- 02按 ID 查询或使用条件构建器
- 03保存、更新、合并与删除实体
- 04控制实体和查询结果的所有权
- 05处理事务与并发版本冲突
适用场景
- 01按 ID 加载或按条件查询实体
- 02保存新对象并刷新已管理对象
- 03处理双向关联及级联删除
- 04在事务中执行持久化操作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tmssoftware/ skills --skill aurelius-objects安装后在 Claude Code 中输入/aurelius-objects确认已加载。
附带文件references/objects.md
详细介绍
使用方法
始终通过 TObjectManager 实例进行操作。所有持久化方法(Save、Flush、Remove 等)都在管理器上调用,不要直接编写原始 SQL。
加载已知 ID: 使用 Manager.Find<T>(Id)——如果对象已加载,则返回缓存的实例;否则查询数据库。
按条件加载多个对象: 使用 Manager.Find<T>(不带参数)获取流式查询构建器,然后调用 .List。
保存新对象: 调用 Manager.Save(obj)——管理器会接管该对象,并从此开始跟踪其更改。Save 会立即执行 INSERT。对于新对象,不要在 Save 后调用 Flush;Flush 仅用于持久化已由管理器管理的对象的更改。
更新由管理器管理的对象: 只需更改其属性并调用 Manager.Flush(或对单个对象调用 Manager.Flush(obj))。无需显式调用“更新”方法。
更新临时对象(来自管理器外部): 调用 Manager.Update(obj)——但请注意,flush 时会写入所有属性,而不只是已更改的属性。
标识冲突: 如果缓存中已有具有相同 ID 的对象,请改用 Manager.Merge<T>(transient),而不是 Update——它会将数据复制到现有的受管理实例中。
删除: 调用 Manager.Remove(obj)——该对象必须由管理器管理(通过此管理器加载,或通过 Save/Update 注册)。
关键规则
对象生命周期
- 受管理实体由管理器拥有,并会在管理器销毁时一并销毁——不要手动释放它们。
- 查询返回列表(
TList<T>)时,释放列表,但不要释放其中的项——这些项仍由管理器管理。 - 投影查询(
ListValues)返回的列表具有OwnsObjects = True;销毁列表时也会销毁其中的项。 - 如果需要在管理器释放后保留实体,请在调用
Free前设置Manager.OwnsObjects := False。 - 如果希望管理器即使在
Save引发异常时也拥有该对象,请在调用Save之前调用Manager.AddOwnership(obj)。
Flush 粒度
- 优先使用
Manager.Flush(singleObject),而不是Manager.Flush(不带参数)。不带参数的形式会遍历管理器的整个缓存,加载了大量对象时可能会很慢。
关联——始终使用对象引用
- 将关联对象赋给关联属性,绝不要赋原始外键值。设置假想的
Invoice.CustomerId字段会绕过 ORM 并导致不一致。 - 对于双向关联,请设置两侧:将父对象赋给子对象的属性,并且将子对象添加到父对象的集合中。
// WRONG — bypasses the ORM:
Invoice.CustomerId := 42;
// CORRECT — assign the managed object:
Invoice.Customer := Manager.Find<TCustomer>(42);
从集合中移除
- 使用
CascadeTypeAll(不启用孤儿移除)时,从集合中移除某项会将其外键设为NULL——该行会作为孤儿保留在数据库中。 - 使用
CascadeTypeAllRemoveOrphan时,从集合中移除某项会在下一次 flush 时删除该行。适用于离开父对象便失去意义的子实体(例如发票明细项)。
延迟加载关联与管理器生命周期
- 访问延迟加载的关联时会立即执行 SELECT。访问延迟加载属性时,管理器必须仍处于活动状态。如果你持有的实体引用中仍有可能访问的延迟加载关联,请不要销毁管理器。
合并与 Update
- 如果缓存中已存在同一 ID、但实例不同的对象,
Update会引发异常——这种情况下请使用Merge<T>。 Merge<T>返回的对象是受管理对象;传入的临时对象不会由管理器管理——请自行释放它。
事务
BeginTransaction应在连接上调用(Manager.Connection.BeginTransaction),而不是在管理器本身上调用。- 始终在
except块中调用Rollback并重新引发异常——绝不要吞掉异常。 - Aurelius 支持嵌套事务;只有最外层的
Commit/Rollback才会操作数据库。
缓存更新与标识 ID
- 当
CachedUpdates = True且实体使用数据库生成的 ID(identity/自增)时,即使其他 SQL 操作会延迟执行,INSERT 也会立即执行,因为后续操作需要生成的 ID。
使用 [Version] 进行并发控制
- 如果带版本号的实体被并发修改,Aurelius 会在刷新时引发
EVersionedConcurrencyControl。请通过刷新对象并重试操作来处理。
参考
如需查看所有操作的完整方法签名、代码示例和详细信息,请阅读 references/objects.md。
参考内容涵盖:TObjectManager 的创建和 TAureliusManager 组件、内存管理(瞬态与持久化、唯一实例、所有权转移)、保存对象(简单保存、带关联保存、级联保存、集合保存)、更新(刷新、Update、Merge、Replicate、更新关联)、查找对象(按 ID、流畅式查询构建器、通过关联查询、即时导航与延迟导航)、刷新、移除(级联与非级联)、逐出、事务、并发控制(变更字段检测、实体版本控制)、缓存更新,以及批量更新。