{"id":"aae32ea9-5314-4802-8bf2-e1319e814a23","shortId":"SMfp5w","kind":"skill","title":"aurelius-objects","tagline":"Save, load, update, delete, merge, and navigate entity objects using TMS Aurelius ORM (TObjectManager). Use when the user asks how to persist or retrieve data with Aurelius, manage object lifetime, work with associations or collections at runtime, handle transactions, use cached ","description":"## Approach\n\nAlways work through a `TObjectManager` instance. All persistence methods (`Save`, `Flush`, `Remove`, etc.) are called on the manager, never written as raw SQL.\n\n**Loading a known id:** use `Manager.Find<T>(Id)` — returns the cached instance if already loaded, otherwise hits the database.\n\n**Loading multiple objects with criteria:** use `Manager.Find<T>` (no argument) to get a fluent query builder, then call `.List`.\n\n**Saving a new object:** call `Manager.Save(obj)` — the manager takes ownership and tracks changes from that point. `Save` executes the INSERT immediately. Do **not** call `Flush` after `Save` for a new object; that is only for persisting changes to already-managed objects.\n\n**Updating a managed object:** just change its properties and call `Manager.Flush` (or `Manager.Flush(obj)` for a single object). No explicit \"update\" call needed.\n\n**Updating a transient object (from outside the manager):** call `Manager.Update(obj)` — but be aware this writes *all* properties on flush, not just the changed ones.\n\n**Conflicting identity:** if an object with the same id is already cached, use `Manager.Merge<T>(transient)` instead of `Update` — it copies data into the existing managed instance.\n\n**Deleting:** call `Manager.Remove(obj)` — the object must be managed (loaded through this manager or registered via `Save`/`Update`).\n\n## Critical Rules\n\n### Object lifetime\n- Managed entities are owned by the manager and destroyed when it is destroyed — **do not free them manually**.\n- When a query returns a list (`TList<T>`), **free the list** but **not the items inside it** — the items remain managed.\n- Projection queries (`ListValues`) return lists with `OwnsObjects = True`; destroying the list also destroys the items.\n- If you need entities to survive after the manager is freed, set `Manager.OwnsObjects := False` before calling `Free`.\n- Call `Manager.AddOwnership(obj)` *before* `Save` if you want the manager to own the object even when `Save` raises an exception.\n\n### Flush granularity\n- Prefer `Manager.Flush(singleObject)` over `Manager.Flush` (no args). The no-arg form iterates the **entire** manager cache and can be slow when many objects are loaded.\n\n### Associations — always use object references\n- Assign the **associated object** to the association property, never a raw foreign key value. Setting a hypothetical `Invoice.CustomerId` field bypasses the ORM and causes inconsistencies.\n- For bidirectional associations, set **both sides**: assign the parent to the child's property *and* add the child to the parent's collection.\n\n```delphi\n// WRONG — bypasses the ORM:\nInvoice.CustomerId := 42;\n\n// CORRECT — assign the managed object:\nInvoice.Customer := Manager.Find<TCustomer>(42);\n```\n\n### Removing from a collection\n- With `CascadeTypeAll` (no orphan removal): removing an item from the collection sets its foreign key to `NULL` — the row stays in the database as an orphan.\n- With `CascadeTypeAllRemoveOrphan`: removing an item from the collection deletes the row on the next flush. Use this for child entities that have no meaning without their parent (e.g. invoice line items).\n\n### Lazy associations and manager lifetime\n- Accessing a lazy-loaded association issues a SELECT at that moment. The manager **must still be alive** when you access a lazy property. Do not destroy the manager while holding references to entities whose lazy associations you may still access.\n\n### Merging vs. Update\n- `Update` raises an exception if the same id is already cached under a different instance — use `Merge<T>` in that case.\n- After `Merge<T>`, the returned object is the managed one; the transient object you passed in is **not** managed — free it yourself.\n\n### Transactions\n- `BeginTransaction` is called on the connection (`Manager.Connection.BeginTransaction`), not on the manager itself.\n- Always `Rollback` in the `except` block and re-raise — never swallow the exception.\n- Aurelius supports nested transactions; only the outermost `Commit`/`Rollback` hits the database.\n\n### Cached updates and identity ids\n- When `CachedUpdates = True` and the entity uses database-generated ids (identity/autoincrement), the INSERT is executed **immediately** even though other SQL is deferred — because the generated id is needed to proceed.\n\n### Concurrency with `[Version]`\n- If a versioned entity is modified concurrently, Aurelius raises `EVersionedConcurrencyControl` on flush. Handle it by refreshing the object and retrying the operation.\n\n## Reference\n\nFor full method signatures, code examples, and details on all operations, read [references/objects.md](references/objects.md).\n\nThe reference covers: TObjectManager creation and TAureliusManager component, memory management (transient vs. persistent, unique instances, ownership transfer), saving objects (simple, with associations, cascades, collections), updating (flush, Update, Merge, Replicate, updating associations), finding objects (by id, fluent query builder, querying through associations, eager vs. lazy navigation), refreshing, removing (with and without cascade), evicting, transactions, concurrency control (changed-field detection, entity versioning), cached updates, and batch/bulk updates.","tags":["aurelius","objects","skills","tmssoftware","agent-skills","claude-code-skill","claude-code-skills","claude-skills"],"capabilities":["skill","source-tmssoftware","skill-aurelius-objects","topic-agent-skills","topic-claude-code-skill","topic-claude-code-skills","topic-claude-skills"],"categories":["skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/tmssoftware/skills/aurelius-objects","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add tmssoftware/skills","source_repo":"https://github.com/tmssoftware/skills","install_from":"skills.sh"}},"qualityScore":"0.456","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 12 github stars · SKILL.md body (5,219 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:07:27.784Z","embedding":null,"createdAt":"2026-04-29T07:00:08.682Z","updatedAt":"2026-05-18T19:07:27.784Z","lastSeenAt":"2026-05-18T19:07:27.784Z","tsv":"'42':421,429 'access':496,516,536 'add':407 'aliv':513 'alreadi':81,145,206,549 'already-manag':144 'also':293 'alway':46,363,594 'approach':45 'arg':342,346 'argument':95 'ask':22 'assign':367,398,423 'associ':36,362,369,373,394,492,501,532,717,726,736 'aurelius':2,15,30,608,666 'aurelius-object':1 'awar':184 'batch/bulk':760 'begintransact':582 'bidirect':393 'block':599 'builder':101,733 'bypass':386,417 'cach':44,78,207,352,550,620,757 'cachedupd':626 'call':60,103,109,129,157,169,179,223,312,314,584 'cascad':718,746 'cascadetypeal':435 'cascadetypeallremoveorphan':461 'case':559 'caus':390 'chang':118,142,153,194,752 'changed-field':751 'child':403,409,478 'code':686 'collect':38,414,433,444,467,719 'commit':615 'compon':703 'concurr':656,665,749 'conflict':196 'connect':587 'control':750 'copi':215 'correct':422 'cover':698 'creation':700 'criteria':91 'critic':240 'data':28,216 'databas':86,456,619,633 'database-gener':632 'defer':647 'delet':7,222,468 'delphi':415 'destroy':252,256,290,294,522 'detail':689 'detect':754 'differ':553 'e.g':487 'eager':737 'entir':350 'entiti':11,245,300,479,529,630,662,755 'etc':58 'even':328,642 'eversionedconcurrencycontrol':668 'evict':747 'exampl':687 'except':333,543,598,607 'execut':123,640 'exist':219 'explicit':167 'fals':310 'field':385,753 'find':727 'fluent':99,731 'flush':56,130,190,334,474,670,721 'foreign':378,447 'form':347 'free':259,269,313,578 'freed':307 'full':683 'generat':634,650 'get':97 'granular':335 'handl':41,671 'hit':84,617 'hold':526 'hypothet':383 'id':72,75,204,547,624,635,651,730 'ident':197,623 'identity/autoincrement':636 'immedi':126,641 'inconsist':391 'insert':125,638 'insid':276 'instanc':51,79,221,554,710 'instead':211 'invoic':488 'invoice.customer':427 'invoice.customerid':384,420 'issu':502 'item':275,279,296,441,464,490 'iter':348 'key':379,448 'known':71 'lazi':491,499,518,531,739 'lazy-load':498 'lifetim':33,243,495 'line':489 'list':104,267,271,286,292 'listvalu':284 'load':5,69,82,87,231,361,500 'manag':31,63,113,146,150,178,220,230,234,244,250,281,305,323,351,425,494,509,524,567,577,592,705 'manager.addownership':315 'manager.connection.begintransaction':588 'manager.find':74,93,428 'manager.flush':158,160,337,340 'manager.merge':209 'manager.ownsobjects':309 'manager.remove':224 'manager.save':110 'manager.update':180 'mani':358 'manual':261 'may':534 'mean':483 'memori':704 'merg':8,537,556,561,723 'method':54,684 'modifi':664 'moment':507 'multipl':88 'must':228,510 'navig':10,740 'need':170,299,653 'nest':610 'never':64,375,604 'new':107,135 'next':473 'no-arg':344 'null':450 'obj':111,161,181,225,316 'object':3,12,32,89,108,136,147,151,165,174,200,227,242,327,359,365,370,426,564,571,676,714,728 'one':195,568 'oper':680,692 'orm':16,388,419 'orphan':437,459 'otherwis':83 'outermost':614 'outsid':176 'own':247 'ownership':115,711 'ownsobject':288 'parent':400,412,486 'pass':573 'persist':25,53,141,708 'point':121 'prefer':336 'proceed':655 'project':282 'properti':155,188,374,405,519 'queri':100,264,283,732,734 'rais':331,541,603,667 'raw':67,377 're':602 're-rais':601 'read':693 'refer':366,527,681,697 'references/objects.md':694,695 'refresh':674,741 'regist':236 'remain':280 'remov':57,430,438,439,462,742 'replic':724 'retri':678 'retriev':27 'return':76,265,285,563 'rollback':595,616 'row':452,470 'rule':241 'runtim':40 'save':4,55,105,122,132,238,318,330,713 'select':504 'set':308,381,395,445 'side':397 'signatur':685 'simpl':715 'singl':164 'singleobject':338 'skill' 'skill-aurelius-objects' 'slow':356 'source-tmssoftware' 'sql':68,645 'stay':453 'still':511,535 'support':609 'surviv':302 'swallow':605 'take':114 'taureliusmanag':702 'though':643 'tlist':268 'tms':14 'tobjectmanag':17,50,699 'topic-agent-skills' 'topic-claude-code-skill' 'topic-claude-code-skills' 'topic-claude-skills' 'track':117 'transact':42,581,611,748 'transfer':712 'transient':173,210,570,706 'true':289,627 'uniqu':709 'updat':6,148,168,171,213,239,539,540,621,720,722,725,758,761 'use':13,18,43,73,92,208,364,475,555,631 'user':21 'valu':380 'version':658,661,756 'via':237 'vs':538,707,738 'want':321 'whose':530 'without':484,745 'work':34,47 'write':186 'written':65 'wrong':416","prices":[{"id":"3061e3b0-83ef-47fe-af0d-dfc3cc3d9b24","listingId":"aae32ea9-5314-4802-8bf2-e1319e814a23","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"tmssoftware","category":"skills","install_from":"skills.sh"},"createdAt":"2026-04-29T07:00:08.682Z"}],"sources":[{"listingId":"aae32ea9-5314-4802-8bf2-e1319e814a23","source":"github","sourceId":"tmssoftware/skills/aurelius-objects","sourceUrl":"https://github.com/tmssoftware/skills/tree/main/skills/aurelius-objects","isPrimary":false,"firstSeenAt":"2026-04-29T07:00:08.682Z","lastSeenAt":"2026-05-18T19:07:27.784Z"}],"details":{"listingId":"aae32ea9-5314-4802-8bf2-e1319e814a23","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"tmssoftware","slug":"aurelius-objects","github":{"repo":"tmssoftware/skills","stars":12,"topics":["agent-skills","claude-code-skill","claude-code-skills","claude-skills"],"license":null,"html_url":"https://github.com/tmssoftware/skills","pushed_at":"2026-04-15T21:13:22Z","description":"Official collection of agent skills from TMS Software","skill_md_sha":"4b2dfe6eb5d389babdefa2c25da6d6664725c983","skill_md_path":"skills/aurelius-objects/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/tmssoftware/skills/tree/main/skills/aurelius-objects"},"layout":"multi","source":"github","category":"skills","frontmatter":{"name":"aurelius-objects","description":"Save, load, update, delete, merge, and navigate entity objects using TMS Aurelius ORM (TObjectManager). Use when the user asks how to persist or retrieve data with Aurelius, manage object lifetime, work with associations or collections at runtime, handle transactions, use cached updates, or control concurrency. Does NOT cover query DSL or criteria/projections (those are in a separate skill). Triggers on requests like \"save an entity with Aurelius\", \"load a customer from the database\", \"add items to a collection\", \"how do I update an object\", \"flush changes\", \"delete a record with Aurelius\", \"merge a transient object\", \"how do transactions work in Aurelius\", \"batch updates Aurelius\"."},"skills_sh_url":"https://skills.sh/tmssoftware/skills/aurelius-objects"},"updatedAt":"2026-05-18T19:07:27.784Z"}}