[英]How to store a binary tree as a property of an entity framework object (code first)
To preface, I am using Entity Framework 6 with a code first approach. 作为序言,我将Entity Framework 6与代码优先方法结合使用。
I created a simple binary tree node class for storing a series of 'rules'. 我创建了一个简单的二叉树节点类,用于存储一系列“规则”。 I want to store the tree as an object in the database but still be able to access it directly as a property of the object it belongs to.
我想将树作为对象存储在数据库中,但仍然能够作为它所属对象的属性直接访问它。
The problem is I encounter this error when trying to create the tree as a property of the object: 问题是尝试将树创建为对象的属性时遇到此错误:
A circular ComplexType hierarchy was detected. Self-referencing ComplexTypes are not supported.
Here is the definition for the table I want to store the tree in: 这是我要在其中存储树的表的定义:
<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
And this is the definition of the Tree: 这是树的定义:
<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
Is there another way I can have Tree as an accessible property of Logic without having to manually serialize/deserialize it? 有没有其他方法可以让Tree成为Logic的可访问属性,而不必手动对其进行序列化/反序列化?
UPDATE: Since I wasn't able to avoid serialization, I decided to just store the tree in the database as a string using postfix notation: "1 2 or 3 4 or and"
From there it is pretty simple to build up the tree. 更新:由于无法避免序列化,我决定只使用后缀表示法将树作为字符串存储在数据库中:
"1 2 or 3 4 or and"
从那里构建树非常简单。
The accepted answer works nicely, provided you are familiar with serialization. 只要您熟悉序列化,可接受的答案就可以很好地工作。 In my particular case the serialization was too complex and I didn't want to take the time to sort it out.
在我的特殊情况下,序列化太复杂了,我不想花时间整理它。
I did put the suggestion to the test with some simpler objects and it worked without issue. 我确实将建议与一些更简单的对象一起进行了测试,并且没有任何问题。
One approach is to make two properties on the Logic class as follows : 1. Store the tree as serialized string in a database property in order to avoid the storage problems - store the whole tree as one object in the database. 一种方法是在Logic类上设置两个属性,如下所示:1.将树作为序列化的字符串存储在数据库属性中,以避免存储问题-将整个树作为一个对象存储在数据库中。 2. Make non-database property through which you access the deserialized tree and its nodes.
2.设置非数据库属性,通过该属性可以访问反序列化的树及其节点。
I suppose that you are going to traverse the tree in code after it is extracted from the database. 我想您将在从数据库中提取树之后遍历代码中的树。
UPDATE Here is an example of a non database property. UPDATE这是非数据库属性的示例。 This is a real example.
这是一个真实的例子。 Do not count in that this is an abstract class.
不要指望这是一个抽象类。 It is the same if it was not.
如果不是,则相同。 The [NotMapped] attribute gets the job done.
[NotMapped]属性完成任务。 Here is a complete reference to Entity Framework Data Annotations where you can find the attribute.
这是对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; }
}
In the getter of the non database property you can implement the deserialization and return the object rather then a string. 在非数据库属性的getter中,您可以实现反序列化并返回对象而不是字符串。 You can implement the serialization in the setter.
您可以在设置器中实现序列化。 This way you will "abstract away" the process of serialization-deserialization inside the non database property and you will continue to work with objects.
这样,您将“取消”非数据库属性内的序列化-反序列化过程,并且您将继续使用对象。
Do not fear of performance hit unless your trees are "humongous". 除非您的树木“巨大”,否则不要担心性能下降。 You can always make a unit test in which you can test the count "barrier" after which the object gets too heavy.
您始终可以进行单元测试,在该单元测试中,可以测试计数“屏障”,之后对象会变得过重。
For the serialization-deserialization you can use Json.NET . 对于序列化/反序列化,可以使用Json.NET 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.