When you do want a class
Classes are fully supported. Reach for one when you want to create nodes with new without a store
(seed data, tests, an import job), want behaviour on the type, or deserialise straight into it from
an external feed. A class can also implement an interface: the interface is the queryable contract,
and the class a form you can create. A class has four extra obligations:
public class Organizer : IOrganizer {
public Guid Id { get; set; }
// The attributes are on IOrganizer: repeating them here has no effect.
public string Name { get; set; } = string.Empty;
public string ContactEmail { get; set; } = string.Empty;
public string Slug { get; set; } = string.Empty;
public DateTime CreatedUtc { get; set; }
public NodeMeta Meta { get; set; } = NodeMeta.Empty; // get and set on a class
}- A parameterless constructor is required. The model builder throws without one.
- Initialise every reference-typed member:
string.Empty,FileValue.Empty,NodeMeta.Empty,[]for embedded maps,new()for relation and reference properties. Interfaces need none of this. Metahas a setter. Still never build one: start withNodeMeta.Empty.- Attributes go on the interface when the class implements one.
Records and structs work too. A record needs the record Foo() { … } form to have a parameterless
constructor. Structs are supported but rarely worth it.