【发布时间】:2014-09-19 17:20:05
【问题描述】:
我的域中有两个聚合根,因此有两个存储库。为了举例,我们将它们称为 BookRepository 和 AuthorRepository。
我正在设计一个 MVC 应用程序,一个页面必须显示一个包含作者列表的表格,每一行都显示作者的个人详细信息。每行的末尾都有一个小按钮,单击该按钮可展开该行并显示一个子表,详细说明作者已出版的书籍。
页面加载时,会执行一些 ajax 从 API 控制器检索作者详细信息并在表中显示数据。 Author 对象中的每个属性几乎都直接映射到一列,但有一个例外,这就是我遇到问题的地方。当且仅当作者没有出版书籍时,我希望禁用每行末尾的按钮。这意味着每个作者记录都必须返回一个布尔值,指示他们是否有任何已出版的书籍。
我的书库有几个这样的方法:
public IEnumerable<Book> GetBooksForAuthor(int authorId);
public bool AnyBooksForAuthor(int authorId);
我的 Book 类有一个名为 AuthorId 的属性,所以我可以通过调用来检索一本书的作者
authorRepository.GetById(book.AuthorId);
我的问题是,为了为上述表格创建一行,我需要像这样创建它:
IEnumerable<Author> authors = authorRepository.GetAll();
foreach (Author author in authors)
{
yield return new AuthorTableRow
{
Name = author.Name,
Age = author.Age,
Location = author.PlaceOfResidence.Name,
HasBooks = this.bookRepository.AnyBooksForAuthor(author.Id)
};
}
上面的代码看起来是正确的,但是在为每个作者调用 this.bookRepository.AnyBooksForAuthor(author.Id) 时会有相当大的性能损失,因为它每次都会执行一次数据库调用。
理想情况下,我想我想要一个 AuthorTableRowRepository 可以执行以下操作:
public IEnumerable<AuthorTableRow> GetAll()
{
return from a in this.dbContext.Authors
select new AuthorTableRow
{
Name = a.Name,
Age = a.Age,
Location a.PlaceOfResidence.Name
HasBooks = a.Books.Any()
});
}
出于以下原因,我犹豫是否要执行此操作:
- AuthorTableRowRepository 是 AuthorTableRows 的存储库,但 AuthorTable 行不是域对象,也不是聚合根,因此不应有自己的存储库。
- 由于 Author 和 Book 都是聚合根,我从 Author 实体中删除了“Books”属性,因为我希望通过 BookRepository 检索书籍的唯一方法。这使得 HasBooks = a.Books.Any() 不可能。我不确定我是否在这里强加我自己被误导的最佳实践。通过 AuthorRepository 获取作者然后通过其 Books 属性来获取 Books 似乎是错误的,反之亦然,通过 Book 对象上的属性获取作者。我想,跨越聚合根边界将是我所说的方式?
其他人会如何解决这个问题?我的担心是没有根据的吗?我最关心的是第一种方法对性能的影响(应该是什么),但我想坚持使用存储库模式和 DDD 的最佳实践。
【问题讨论】:
-
为什么要投反对票...?请解释一下,以免我下次出错?
标签: entity-framework repository domain-driven-design aggregateroot