如何将二叉树存储为 entity framework 对象的 属性(代码优先)

How to store a binary tree as a property of an entity framework object (code first)

作为序言,我使用 Entity Framework 6 代码优先方法。

我创建了一个简单的二叉树节点 class 用于存储一系列 'rules'。我想将树作为一个对象存储在数据库中,但仍然能够作为它所属对象的 属性 直接访问它。

问题是我在尝试将树创建为对象的 属性 时遇到此错误:

A circular ComplexType hierarchy was detected. Self-referencing ComplexTypes are not supported.

这里是table的定义我想把树存储在:

    <Table("Logic", Schema:="dbo")> _
Public Class Logic
    <Key>
    Public Property ID As Integer
    Public Property Expression As String
    Public Property Tree As LanguageTest5.Survey.BinaryExpressionNode
End Class

这是树的定义:

    <Serializable, ComplexType>
Public Class BinaryExpressionNode
    Public Property Value As Object
    Public Property LeftNode As BinaryExpressionNode
    Public Property RightNode As BinaryExpressionNode

    Public Sub New(Val As Object)
        Value = Val
    End Sub
End Class

有没有其他方法可以让 Tree 作为 Logic 的可访问 属性 而无需手动 serialize/deserialize 它?

更新: 由于我无法避免序列化,我决定使用后缀表示法将树作为字符串存储在数据库中: "1 2 or 3 4 or and" 从那里构建树非常简单。

如果您熟悉序列化,接受的答案效果很好。在我的特殊情况下,序列化太复杂了,我不想花时间来解决它。

我确实用一些更简单的对象对建议进行了测试,并且没有问题。

一种方法是在逻辑 class 上创建两个属性,如下所示: 1. 将树作为序列化字符串存储在数据库中 属性 以避免存储问题 - 将整棵树作为一个对象存储在数据库中。 2. 使非数据库属性通过它访问反序列化树及其节点。

我想你打算在从数据库中提取树后用代码遍历树。

更新 这里是一个非数据库的例子属性。这是一个真实的例子。不算是抽象的class。没有也一样。 [NotMapped] 属性完成了工作。这是对 Entity Framework Data Annotations 的完整参考,您可以在其中找到该属性。 :

public abstract class Document : Entity
    {
        [Required]
        [StringLength(50)]
        public virtual string Egn { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public virtual Guid Guid { get; set; }

        public virtual string Subject { get; set; }

        [NotMapped]
        public abstract EntityDataAccessKeyType EntityDataAccessKeyType { get; }
        [NotMapped]
        public abstract int EntityDataAccessKeyId { get; }
    }

在非数据库 getter 中 属性 您可以实现反序列化和 return 对象而不是字符串。您可以在 setter 中实现序列化。这样,您将 "abstract away" 在非数据库 属性 中进行序列化-反序列化的过程,并且您将继续使用对象。

除非你的树是 "humongous",否则不要担心性能下降。您始终可以进行单元测试,在其中测试对象变得过重的计数 "barrier"。

对于序列化-反序列化,您可以使用 Json.NET