简体   繁体   English

如何将二叉树存储为实体框架对象的属性(代码优先)

[英]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.

相关问题 如何在不首先选择对象的情况下更改实体框架中复杂类型属性的ID? - How to change the ID of a complex type property in entity framework without first selecting the object? 首先使用Entity Framework代码时如何使用外键 - How to work with foreign keys when using Entity Framework code first 如何在代码优先实体框架中提供数据库配置设置? - How to provide database configuration settings in code-first Entity Framework? 实体框架代码优先——外键关系 - Entity Framework code first - foreign key relationship 实体框架代码第一个可为空的整数 - Entity Framework Code First Nullable Integer 实体框架5,代码优先延迟加载不起作用 - Entity Framework 5, Code First Lazy Loading Not Working 实体框架可导航属性未设置为对象实例? - Entity Framework Navigable Property Not Set to Instance of Object? 在Entity框架中,我们可以先使用Model,先使用DB,然后使用Code,但是如何以编程方式创建表 - In Entity framework, we can use Model first, DB first, Code first but how can we create table programmatically 如何使用实体框架首先对VB .net项目进行反向工程代码 - How to Reverse Engineer Code First for a VB .net project using the Entity Framework 实体框架和属性容器 - Entity Framework and property containers
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM