MongoDB C# 实体映射: "一对多关系"

7

我是一名MongoDb的新手,但我知道在文档数据库中谈论关系是不合适的。无论如何,我正在尝试使用它,只是为了了解它是否符合我的需求以及它的限制在哪里。

我在我的领域中只有一个简单的C#实体:

class Person
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }

    public ICollection<Person> Friends { get; set; }
}

我希望序列化过程能够将该集合转换成一种类似于列表的形式

["...api/persons/1", "...api/persons/2", ...]

有没有某种方式可以实现?

请查看MongoDB.Entities包装库。它可以轻松处理一对一、一对多和多对多关系。 - Dĵ ΝιΓΞΗΛψΚ
@DĵΝιΓΞΗΛψΚ 你好,我已经使用了你的库一段时间了,但最近我无法找到让 System.Text.Json 序列化你的 Many<> 和 One<> 字段的方法。有什么办法可以序列化 Json 吗? - user2617470
@踩我的都死马 不要这样做!!!你不应该将数据实体暴露给表示/用户界面层。你应该使用DTO并映射到和从数据实体中仅传递UI所需的确切数据/信息,以供特定视图/功能使用。即使可以序列化Many<T>属性,这也是一个非常糟糕的想法。例如,如果该属性指向1000个相关实体,会怎样?这是个坏主意。如果需要进一步帮助,请在GitHub上创建一个问题,附上您的确切用例。展示您的数据实体(仅包含相关属性)和期望的输出。 - Dĵ ΝιΓΞΗΛψΚ
1个回答

14

在文档数据库中,关系是一种有点“臭味”的东西。

不,完全不是这样。遗憾的是,这种观念很普遍,但在非关系型数据库中使用关系并没有问题,只是管理这些关系的方法不同罢了。

让我们来看看你的模型:

public ICollection<Person> Friends { get; set; }

你可能已经发现,这会序列化一个文档的树形结构

{ "name" : "doe",  
  "firstName" : "john", 
  "friends" : [ 
      { "name" : "rogers", 
        "firstName" : "mike", 
        "friends" : [ {"name" : "myers", "firstName" : "lucy", ... },  
        ... ] },
 ... ] }

换句话说,这些内容不会被序列化为关系,而是作为“嵌入式文档”存储。
如果您想要关系,则最简单和最干净的方法是存储关系。
class Person {
    public ObjectId Id { get; set; }
    public string FirstName { get; set; }
    public List<ObjectId> FriendIds { get; set; }
}

这将需要手动将您的领域模型翻译为与数据库兼容的模型,这引出了一个问题,为什么您首先想要一个领域模型。
领域模型的问题在于它们需要在RAM中有一个部分序列化的图形。这似乎从.NET方面来说很方便,例如,您可以执行以下操作:
person.Friends.First().Friends.Where(p => p.Name == "Doe").Friends.Last...

但是从数据库中获取所有这些信息的方法不是非常清楚,因为这个简单的一行代码可能需要至少4次往返数据库。虽然这样的映射可以实现(透明激活),但它会隐藏程序员需要知道的很多重要信息。

如果加入修改(和修改跟踪)到方程式中,情况会变得非常混乱。

此外,该模型在我看来像是一个m:n关系(一个人可以有很多朋友,一个人也可以被许多其他人称为朋友,对吧?)。对于m:n关系,嵌入引用列表可能不是最好的方法,但有一些替代方案


非常感谢您提供如此清晰的答案。是的,意图是要有m:n关系。 - Matteo Fontana
我刚刚阅读了您在末尾链接的另一个答案,我想我明白了要点。非常感谢! - Matteo Fontana

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