0

我在我的域中有两个聚合根,因此有两个存储库。为了举例,我们将它们称为BookRepository和AuthorRepository。EF,知识库和跨越总体边界

我在设计一个MVC应用程序,一个页面必须显示一个包含作者列表的表格,每行显示作者的个人详细信息。在每行的末尾是一个小按钮,可以通过单击该按钮来展开该行并显示详细列出作者出版书籍的子表。

页面加载时,会执行一些ajax以从API控制器检索作者详细信息并在表中显示数据。作者对象中的每个属性几乎直接映射到列,但有一个例外,这就是我遇到问题的地方。我希望每行末尾的按钮都被禁用,当且仅当作者没有发布书籍时。这意味着每个作者记录必须返回一个布尔值,表明他们是否有任何已发布的书籍。

我的书库有这样几个方法:

public IEnumerable<Book> GetBooksForAuthor(int authorId); 

public bool AnyBooksForAuthor(int authorId); 

和My 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行不是域对象,也不是聚合根,因此不应有自己的存储库。
  • 由于作者和书籍都是聚合根,所以我从作者实体中删除了“书籍”属性,因为我想要通过BookRepository检索书籍的唯一方法。这使HasBooks = a.Books.Any()不可能。不过,我不确定自己是否在这里强加了自己误导的最佳做法。通过AuthorRepository获取作者并通过其Books属性获取作者似乎是错误的,反之亦然,通过Book对象上的属性获取作者。穿越聚合根边界将是我认为的方式,我想呢?

其他人怎么解决这个问题?我的担心是否没有根据?我主要关心的是第一种方法的性能问题(应该是什么),但我想遵循Repository模式和DDD的最佳实践。

+0

为什么downvotes ...?请解释一下,以便下次避免任何错误? – 2014-10-01 12:42:47

回答

0

我最终解决这个问题的方式是从数据库中的视图创建一个实体。我将实体命名为“AuthorSummary”,并创建了一个不包含任何Add()方法的AuthorSummaryRepository,只是检索方法。

0

我会坚持第一种方法,但尝试优化书库知识库中的方法。例如,您可以一次加载这些信息,并使用内存查找来加快速度。像这样,你需要2个查询,而不是每个作者1个。

+0

bookrepository方法如何优化?这是一个非常简单的向.Any()查询数据库,我不知道我能做些什么来优化它? – 2014-09-23 10:43:18

+0

那么,如果bookrepository中有作者的书籍数量的内存列表,则只需要在循环之前初始化列表,如下所示; 'this.bookRepository.LoadBooksByAuthor(); IEnumerable authors = authorRepository.GetAll(); 的foreach(在作者单位Author) { 产量返回新AuthorTableRow { 名称= author.Name, 年龄= author.Age, 位置= author.PlaceOfResidence.Name, HasBooks = this.bookRepository.AnyBooksForAuthor(作者.Id)//这个调用不会进入数据库,而只是一个内存查询 }; }' – 2014-09-24 04:22:49

+0

如果bookRepository有数百万本书籍加载,那真的会更好吗? bookRepository无法加载表的子集,因为在作者查询执行之前,它不知道您需要哪些书籍信息。 – 2014-09-24 10:29:18