aggregate roots - Envivo-Software/Envivo.Fresnel GitHub Wiki

Aggregate Roots

Use an Aggregate Root (AR for short) when all objects within the aggregate must be saved at the same time, and within a single atomic transaction. ARs will make most sense when your model can be persisted to a database or store.

To declare a class as an AR, implement the IAggregateRoot interface:

/// <summary>
/// A customer
/// </summary>
public class Customer : IAggregateRoot //👈
{
    /// <summary>
    /// <inheritdoc/>
    /// </summary>
    [Key]
    public Guid Id { get; set; }

    /// <summary>
    /// The customer's name information
    /// </summary>
    [Relationship(RelationshipType.Owns)]
    public NameInfo Name { get; set; }

    /// <summary>
    /// The customer's default address
    /// </summary>
    [Relationship(RelationshipType.Owns)]
    public Address Address { get; set; }

    /// <summary>
    /// The customers contact phone number
    /// </summary>
    [Relationship(RelationshipType.Owns)]
    public PhoneNumber Phone { get; set; }

    public string Email { get; set; }

    /// <summary>
    /// The customer's account, where billing and payment occurs
    /// </summary>
    [Relationship(RelationshipType.Owns)]
    public IAggregateReference<Account> Account { get; set; }

    /// <summary>
    /// The user's entry into the online shopping site
    /// </summary>
    [Relationship(RelationshipType.Owns)]
    public IAggregateReference<WebUser> WebUser { get; set; }
}

When the Customer object is saved from the UI, Fresnel will save all of it's nested objects too:

As Fresnel is primarily a prototyping tool, it doesn't follow the strictness of persisting ARs (e.g., isolating AR boundaries, transaction management, or concurrency conflicts).

Instead, the UI simply saves the top-level AR and any referenced ARs that are downstream. Note that saving a downstream AR in isolation will NOT cause the top-level AR to be saved.

⚠️ **GitHub.com Fallback** ⚠️