I've come to a bit of an impasse with the best way to implement a DDD problem, and am hoping for some advice from those with more experience, please.
I have a RecipeCollection, which has a collection of type Recipe (as you might expect). The abbreviated code looks like this:
public class RecipeCollection : IEntity<RecipeCollectionId>, IAggregateRoot
{
private readonly RecipeCollectionId id = new();
private readonly List<RecipeId> recipeIds = new();
public void AddRecipe(RecipeId recipeId) { /* not sure what to do here! */ }
...
}
public class Recipe : IEntity<RecipId>
{
public readonly string Name { get; private set; }
...
}
One of the business rules is that a Recipe cannot have the same Name within a RecipeCollection. The obvious place to enforce this invariant is within RecipeCollection, when adding a new Recipe. However, RecipeCollection only holds a list of RecipeId, not a list of Recipe itself.
Ideally, RecipeCollection would hold a collection of Recipe, which would make checking for duplicate Recipe.Name easy. However, RecipeCollection holds a collection of RecipeId. It does this to avoid potential problems such as loading a RecipeCollection from memory, which loads all its Recipes, which each in turn load another collection, and so on, and before you know it, you've loaded the entire database. I know I could use lazy loading, but I may use a data store where this isn't possible, so I'm forced to hold a collection of RecipeId.
Is the best solution, in this case, to have the calling code, i.e. the command handler that retrieves the RecipeCollection from the repo, check there are no duplicated Recipe Names before adding the Recipe? This would leak the business logic out of the Aggregate root in this instance, which is why I haven't committed to this solution. Or is there another solution/pattern I'm missing?