如何将二叉树存储为 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。
作为序言,我使用 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。