The five shapes
// 1. Symmetric one-to-one: twin venues. Both ends are the same property.
public class PairedWith : OneOne<IVenue> {
public class Pair : One { }
}
// 2. Directional one-to-one: an organizer's primary contact.
public class PrimaryContact : OneToOne<IOrganizer, IAttendee> {
public class Organizer : OneFrom { } // on IAttendee
public class Contact : OneTo { } // on IOrganizer
}
// 3. Directional one-to-many: the workhorse.
public class EventsAtVenue : OneToMany<IVenue, IEvent> {
public class Venue : One { } // on IEvent: its one venue
public class Events : Many { } // on IVenue: its many events
}
// 4. Symmetric many-to-many: friends.
public class Friends : ManyMany<IAttendee> {
public class Peers : Many { }
}
// 5. Directional many-to-many: events and their attendees.
public class Attendance : ManyToMany<IEvent, IAttendee> {
public class Events : ManyFrom { } // on IAttendee
public class Attendees : ManyTo { } // on IEvent
}| Base class | Symmetry | Cardinality | Nested classes |
|---|---|---|---|
OneOne<T> |
symmetric | 1↔1, same type | One |
OneToOne<TFrom, TTo> |
directional | 1↔1 | OneFrom, OneTo |
OneToMany<TOne, TMany> |
directional | 1↔N | One, Many |
ManyMany<T> |
symmetric | N↔N, same type | Many |
ManyToMany<TFrom, TTo> |
directional | N↔N | ManyFrom, ManyTo |
There is no zero-or-one and no separate many-to-one: use OneToMany from the other end. When the
edge itself carries data, such as a ticket price or a role, make the edge a node type with a
relation to each side.