我正在构建一个小型 Recipe Organizer MVC 项目,首先使用 EntityFramework 代码和 Sql Server Compact 版本,以此来了解更多关于 DDD 和存储库模式的信息。
这是我的一些域实体,我已针对这个问题简化了它们。
public class Recipe {
public int Id { get; set; }
[Required]
public string Name { get; set; }
/// <summary>
/// Represents a common meal type of “Breakfast, Lunch or Dinner”
/// or type of course “Appetisers, Soups, Salads, Fish, Poultry & Game, Meat, Side dishes, Desserts, Miscellaneous", etc.
/// (for scope I am not considering brunch or supper or any other type)
/// </summary>
[Required]
public Course Course { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
public class Ingredient {
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Course {
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
在我看来,对于这个项目的范围,我会说 Recipe 是聚合根,Ingredient 和 Course 是 Recipe 的聚合。
如果我采用此示例并使用 MVC 脚手架为我提供存储库模式的示例实现,我将获得以下接口(interface)和一个实现该接口(interface)并具有对 EF DB 上下文的引用的 EFRecipeRepository 类。
public interface IRecipeRepository
{
IQueryable<Recipe> All { get; }
IQueryable<Recipe> AllIncluding(params Expression<Func<Recipe, object>>[] includeProperties);
Recipe Find(int id);
void InsertOrUpdate(Recipe recipe);
void Delete(int id);
void Save();
}
遵循此指南:
In the context of the repository pattern, aggregate roots are the only objects your client code loads from the repository.
The repository encapsulates access to child objects - from a caller's perspective it automatically loads them, either at the same time the root is loaded or when they're actually needed (as with lazy loading).
我希望向该界面添加更多内容,以便通过食谱获得成分或类(class)。
我遇到的问题是我想在我的 View 中添加一些仅涉及成分或类(class)的功能,例如:所有不同类型类(class)的导航(不仅仅是与食谱相关的类(class))和自动-完整的配料 list 。
在我的项目范围内,成分不存在于食谱之外,因此它应该是食谱的集合似乎是可行的。然而,当然似乎它本身应该是一个聚合根,因为它是如何独立存在的?
我正在努力了解这一切应该如何运作,如果我想获得每个成分的列表,那意味着我首先必须使用配方存储库加载所有配方才能找到所有成分?
当然也有类似的问题,只是它被用作对食谱进行分类的一种方式,因此也可以存在于该边界之外。
我是否缺少某些概念?也许是一种创建用于此类表示层要求的服务的方法?有没有人对如何做到这一点有任何意见?或者有什么更好的建议?谢谢
附带说明一下,这是一个小项目,DDD 可能不是最好的方法,但我确实发现存储库模式对于我的域模型中的持久性无知非常有用。
谢谢
最佳答案
I am struggling to get a vision of how this all should work, if I wanted to obtain a list of every Ingredient would that mean that I would first have to use the Recipe Repository to load up all the Recipes in order to find all the Ingredients?
如果您只需要一个自动完成的不同成分名称的列表,我确实会提供一项服务,从数据库中提取必要的报告。我非常喜欢在聚合中插入的报告,因为它们就是 - 报告。您只是不应该让服务从聚合内部返回可用实体(即不返回 Ingredient[]),因为这会向调用者打开聚合边界。只需返回一个 string[] 或类似的。
话又说回来,除了最琐碎的应用程序之外,我会在所有应用程序中同时考虑 Course 和 Ingredient 聚合根。配料可以没有食谱吗?绝对地! “糖”#1(属于食谱#1)与“糖”#2(属于食谱#2)有什么不同吗?我不这么认为。有糖。还有使用糖的食谱。让配料聚集根很有意义。例如,您可以按成分轻松浏览您的食谱。
类(class)也是如此,这是一个绝对有意义的概念。
对于不应该是聚合根的概念的一个很好的例子是订单行(也就是说,“3 台 Foobar 电视每台 700 美元”)。没有订单,订单行就没有意义。但即使在这种情况下,在订单行上生成报告的服务也是有意义的(理论上)并且是合法的 IMO。例如,人们可能想知道通常会一起购买多少台 Foobar 电视,以便介绍出色的新 Foobar 电视 3 件装(是的,随便什么......)。这又意味着在数据库中搜索通常无法直接访问的数据。
关于c# - 领域驱动设计和聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9435917/