C# MongoDB (noRM) - 使用嵌入式文档实现仓储模式

4
我正在开发一个类似于Stack Overflow的应用程序(问题/答案等)。模型看起来像这样(简化):
使用C# / ASP.net MVC建模NoSQL论坛应用程序
class Question
{
    public string Title { get; set; }
    public string Body { get; set; }
    public DateTime DateCreated { get; set; }

    public string UserName { get; set; }

    public List<Answer> Replies { get; set; }
}

class Answer
{
    public string Body { get; set; }
    public DateTime DateCreated { get; set; }

    public string UserName { get; set; }
}

我的文档只是一个文档,其中包含了“答案”。

我正在尝试为这种方法设计我的代码库。

我应该有两个单独的代码库吗?例如:

interface IQuestionRepository
{
    void PutQuestion(Question question);
    Question GetQuestion(string questionID);
}  

interface IAnswerRepository
{
    void PutAnswer(string questionID, Answer Answer);
    Answer GetAnswer(string answerID);
}

Or something like this:

interface IPostRepository
{
    void PutQuestion(Question question);
    Question GetQuestion(string questionID);
    void PutAnswer(string questionID, Answer Answer);
    Answer GetAnswer(string answerID);
}

3个回答

6
你的模型本质上存在缺陷。
问题应该是根文档。
答案应该是根文档。
虽然这篇关于RavenDB的文档建模信息,但大部分内容都可以直接使用:http://codeofrob.com/archive/2010/12/21/ravendb-document-design-with-collections.aspx 编辑:值得一提的是,你的模型存在缺陷的原因在于文档数据库需要让文档模拟事务边界。想象一下在Stack Overflow中进行编辑的情况,多人添加和更新答案,所有这些都会更改根文档,而发布者正在更新问题。单个对象上的争用量将非常问题。
RavenDB提供了所谓的“补丁”,可以让您操作文档结构的一部分而不是整个文档,以解决此类问题,但最好在一开始避免此设计,而不是通过大大增加持久性模型的复杂性来尝试使其工作,并处理复杂的并发情况。
回答具体问题后,然后您将拥有AnswersRepository和QuestionsRepository。

我没有注意到 Rob 的这篇文章。现在我已经阅读了它,并对我的模型进行了一些更改。 - Alex
@alexjamesbrown 我知道你接受了这个问题的答案,现在时间过去了,你觉得这是正确的方法吗? - Chris Marisic
1
冒着被炮轰的风险,我不认为该模型本质上有缺陷。在我看来,将事务边界作为正确的设计模型的想法是不完整的,因为它没有考虑到最常见的用例,即在 stackoverflow 示例中读取数据而不是写入数据。按照这里的逻辑,我们会对“简化”最不常见的用例施加额外的查询开销。此外,MongoDB 具有针对“许多人同时编写”的场景的原地更新功能。 - tony.wiredin
1
@eggheaddesign 我们不得不同意不同的看法,我完全坚持我的观点,即实际事务边界的存在位置。NoSQL系统通常也是面向读取的,因此必须单独查询的“成本”并不是我选择处理极端并发数据访问的代价。此外,这是优化减少查询数量的问题,而且有方法可以克服这个问题,这取决于提供商。我只能谈论RavenDB,但可以存储伪子文档,您可以在单个查询中检索它们。 - Chris Marisic

0

我认为最好为每个聚合根(仅限于问题文档)创建存储库。


-1

你不需要一个答案的存储库。从域的角度来看,你应该将答案添加到你的问题对象中。问题存储库应该完成这项工作,因为问题看起来像是一个聚合根,你应该为每个聚合根(而不是每个实体)拥有一个存储库。

你应该小心不要创建一个贫血领域模型


-1 这个设计会导致大量的工作量。请看我的回答,了解为什么这是一个糟糕的设计。领域建模和持久化建模是两个非常不同的主题,后者极其针对持久化机制。许多时候,持久化模型可以接受领域实体,但有时这样做会很糟糕,比如这种情况。 - Chris Marisic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接