Create does not store. Follow it with Insert, and call Update after changing a loaded node.
Async writes skip transaction plugins.Insert, Update, Delete and Execute run them;
InsertAsync, UpdateAsync, ExecuteAsync and the other async writes do not. Neither the CMS's
save checks nor your own plugins see those writes.
A read by id ignores read access.db.Get(id) and TryGet return the node whatever its read
access, while queries and relation properties apply it. Before showing a node the visitor reached
by id, ask RelatudeCmsContext.CanRead(key), or query for it.
Admin is for trusted code. Content rendered for the visitor from RelatudeCmsContext.Admin
shows what the visitor may not read.
Serialize projections, never nodes. Relation ends are enumerable, so a serializer walks the
graph. For the same reason, [FromContent] skips validation.
A new address can come back changed. The store adds -2, or a higher number, when the URL is
taken, and keeps only plain ASCII. Read the address back rather than assume it.
Values in db.raw() are literals. There, a decimal property compared with 100 is compared
with 0. For decimals and dates, use the builder's conditions or rawQuery with typed parameters
(chapter 19).
A transaction plugin sees whole nodes and single properties. The CMS interface saves only what
changed, so a rule in OnBeforeNodeAction alone misses its saves. Check OnBeforePropertyAction
too.