Summary#
Entity About; is a member that references a row of any type the app keeps — a ticket, an order, a draft — where
an ordinary reference (Ticket Ticket;) names one. It is what a kit holds when it is "about some record" it cannot
know the type of: a notification, a comment, a question.
It reads as its reader: a row the person reading it may not read reads null — not a shell carrying its id — so
== null, a type test and Records.Title all say nothing about it.
Signature#
[Required] Entity About; // any row of any entity type — never a class or an interface value
Entity? Seen; // optional
[OnDelete(Remove)] Entity About; // what deleting the row it references does to this one — see [OnDelete]
note.About = ticket; // any row
if (note.About is Ticket t) { … } // C#'s declaration pattern, straight off the member
var t = note.About as Ticket; // null when it is not a Ticket — or not readable
note.About == ticket // in a query too: compares the reference
note.About.Id // in a query too: the key it holdsDescription#
What may it reference?#
Any row of any entity — the app's own and every kit's. Not a class value or an interface: those are not stored,
so there is nothing to reference. An Entity member accepts a row and refuses anything else where it is written.
What does it read as?#
The row, read under the reader's own rules — as every read is. Because the schema promises nothing about which
type a reference holds, it cannot promise that the reader may read it either, so a row the reader may not read reads
null rather than a row with its fields masked. Reading many — a list of notifications, each about some record — reads
the records together, one query per type, not one per row. SECURITY-INVARIANT
an-entity-reference-reads-as-the-caller.
What the member holds does not change with who reads it: a person who may not read the referenced row may still
write the row that holds the reference, and [Required] is satisfied by the key it holds.
Which type is it?#
Test it with C#'s own is / as / cast. if (x.About is Ticket t) binds t straight off the member. The type is kept
beside the key, as a column named <Member>Type (AboutType) holding the entity's name, so a query can ask
n.AboutType == "Ticket" — and the compiler refuses a member of yours with that name.
What happens when its row is deleted?#
By default nothing: the member keeps the key and reads null. Say otherwise with [[entity-on-delete|[OnDelete]]]:
Remove deletes the holding row with it, Clear empties the member.
What do I show for it?#
Its record facts, which every row has: Records.Title(x) (what it is called),
Records.Link(x) (where it opens), Records.Noun(x) (what kind of thing it is) and Records.MayRead(person, x).
Examples#
[Principal] entity Person {
[Required, MaxLength(100)] string Name;
security { allow read when IsAuthenticated; }
}
[Title(Subject)]
entity Issue {
[Required, MaxLength(200)] string Subject;
bool Private;
[Required] Person Reporter;
security { allow read, create when IsAuthenticated where !Private || Reporter == user; }
}
[Title($"Invoice {Number}")]
entity Invoice {
[Required, MaxLength(20)] string Number;
security { allow read, create when IsAuthenticated; }
}
/// A comment about an issue or an invoice — or any record the app keeps later.
entity Comment {
[Required, MaxLength(2000)] string Text;
[Required, OnDelete(Remove)] Entity About;
security { allow read, create when IsAuthenticated; }
}
/// What the reader sees of each comment: the record's title, or nothing when they may not read the record.
public List<string> CommentLines() {
List<string> lines = [];
foreach (var c in Comment.OrderBy(c => c.Text).ToList()) {
var about = c.About == null ? "(a record you cannot see)" : Records.Title(c.About);
if (c.About is Issue i && i.Private) { about = about + " (private)"; }
lines.Add(about + ": " + c.Text);
}
return lines;
}
/// The comments about one record — the reference compared in the query.
public int CommentsOn(Invoice invoice) { return Comment.Count(c => c.About == invoice); }See also#
- Records — what any record is called, where it opens, who may read it — what any record is called, where it opens, and who may read it
- [OnDelete] — what deleting the referenced row does
- [Title] on an entity — what each record is called
- relations — a reference to ONE type, with its collection on the other side
- Security.MayRead — may THIS person read this row, under their own rules — the reader's own rules, which every read obeys