在文档数据库中,关系是一种有点“臭味”的东西。
不,完全不是这样。遗憾的是,这种观念很普遍,但在非关系型数据库中使用关系并没有问题,只是管理这些关系的方法不同罢了。
让我们来看看你的模型:
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关系,嵌入引用列表可能不是最好的方法,但有一些替代方案。