鉴于文档数据库(如RavenDB)是非关系型的,您如何避免复制多个文档共有的数据?如果可以复制数据,你如何维护这些数据呢?
答案 0 :(得分:12)
使用文档数据库,您必须在某种程度上复制数据。该学位取决于您的系统和用例。
例如,如果我们有一个简单的博客和用户聚合,我们可以将它们设置为:
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
public class Blog
{
public string Id { get; set; }
public string Title { get; set; }
public class BlogUser
{
public string Id { get; set; }
public string Name { get; set; }
}
}
在这个例子中,我在Blog类中嵌套了一个BlogUser类,其中包含与Blog关联的User Aggregate的Id和Name属性。我已经包含了这些字段,因为它们是Blog类感兴趣的唯一字段,在显示博客时不需要知道用户的用户名或密码。
这些嵌套类将依赖于您的系统用例,因此您必须仔细设计它们,但一般的想法是尝试设计可以通过单次读取从数据库加载的聚合,它们将包含所有显示或操纵它们所需的数据。
这导致了User.Name更新时会发生什么的问题。
对于大多数文档数据库,您必须加载属于更新用户的所有Blog实例,并更新Blog.BlogUser.Name字段并将它们全部保存回数据库。
Raven略有不同,因为它支持更新的设置功能,因此您可以针对RavenDB运行单个更新,这将更新用户博客的BlogUser.Name属性,而无需您加载它们并单独更新它们
在RavenDB中进行更新的代码(手动方式)适用于所有博客:
public void UpdateBlogUser(User user)
{
var blogs = session.Query<Blog>("blogsByUserId")
.Where(b.BlogUser.Id == user.Id)
.ToList();
foreach(var blog in blogs)
blog.BlogUser.Name == user.Name;
session.SaveChanges()
}
我在SaveChanges中添加了一个例子。 RavenDB客户端使用工作单元模式,因此这应该发生在此方法之外的某处。
答案 1 :(得分:2)
你的问题恕我直言,没有一个“正确”的答案。它真正取决于您复制的数据的可变性。
查看RavenDB documentation有关文档数据库设计与关系的大量答案,但请特别查看Document Structure Design Considerations文档的“关联管理”部分。简而言之,当文档DB不希望在文档中嵌入共享数据时,它们使用ID引用的概念。这些ID与FK不同,它们完全取决于应用程序,以确保完整性和解决方案。