在Raven中存储带有父指针和子指针的树

本文关键字:指针 Raven 存储 | 更新日期: 2023-09-27 18:04:46

我有一个树结构,其中的节点既有子指针又有父指针。我在很好地序列化它时遇到了一些问题(这将用于配置,因此它需要对操作/配置管理器具有一定的可读性),并且在尝试了序列化约定和属性的不同组合之后,我仍然卡住了。

我的类型是这样的:

public class NestedConfigurationTree<T> where T : class
{
    public InternalNode<T> _root { get; set; }
    public class InternalNode<TValue> where TValue : class
    {
        public Dictionary<string, InternalNode<TValue>> _children { get; set; }
        public InternalNode<TValue> _parent  { get; set; }
        public TValue _value  { get; set; }
    }
}

当我允许循环引用([JsonObject(IsReference = true)])时,每个节点得到的JSON看起来像这样:

        "$id": "3",
        "_children": {
          "ConfigurationItem": {
            "$id": "4",
            "_children": {},
            "_parent": {
              "$ref": "3"
            },
            "_value": "Some value"
          }
        },

这显然会让最终用户感到困惑,他们不想要$id和_parent这些东西。由于父节点在文档结构中非常明显,我是否可以避免序列化它,并在加载时重新创建它?

还有,是否有可能避免拥有公共属性?我最初将其写为private readonly字段,但这使得序列化器忽略了所有这些字段。

在Raven中存储带有父指针和子指针的树

并非所有内容都适合直接存储在数据库中。您已经展示了这种场景的一个很好的例子。如果您的最终用户会对它感到困惑,那么您想要针对它编写的任何查询也会感到困惑。

我的建议是有一个没有这些引用的树版本。序列化,看起来像这样:

{
  "Value" : "A",
  "Children" : [
    {
      "Value" : "B",
      "Children" : [
        {
          "Value" : "C",
          "Children" : [
            {
                "Value" : "D",
            }
          ]
        },
        {
          "Value" : "E",
          "Children" : [
            {
                "Value" : "F",
                "Children" : []
            },
            {
                "Value" : "G",
                "Children" : []
            }
          ]
        }
      ]
    }
  ]
}

在序列化时,您可以忽略父/子链接,而在反序列化时,您可以将它们重新连接起来。

您可以在自定义的JsonConverter中完成所有这些,而不是使用第二组类,它为您提供了如何序列化或反序列化任何特定实体的细粒度控制。

另一个选项(也许是最简单的)是使用方法而不是属性来遍历链接。换句话说,不是:

Node Parent { get; }
IEnumerable<Node> Children { get; }

你可以使用:

Node GetParent();
IEnumerable<Node> GetChildren();

方法在序列化过程中不会被跟踪,所以这可能是最简单的事情。