【问题标题】:Breezejs Uncaught TypeError: Converting circular structure to JSONBreezejs Uncaught TypeError:将循环结构转换为 JSON
【发布时间】:2013-06-14 02:34:36
【问题描述】:

我有一个使用 Hot Towel 模板的 ASP.Net MVC SPA,即轻柔、淘汰赛、实体框架(代码优先)、durandal 等。

在我的 EF 模型中,我有一个名为“Section”的类,它具有自引用关联。每个部分都属于一个“文档”,每个部分也有一个“项目”的集合:

    public class Section : CommonBase
    {
        ...

        public Guid DocumentId { get; set; }
        public Document Document { get; set; }

        ...

        public List<Item> Items { get; set; }

        public Guid? ParentId { get; set; }
        public Section Parent { get; set; }

        public List<Section> Children { get; set; }

        ...
   }

   public class Item : CommonBase
   {
       ...

       public Guid SectionId { get; set; }
       public Section Section { get; set; }

       ...
   }

当我通过 Breeze 查询和 BreezeController 方法加载文档时,我会加载“Sections”和“Items”:

    var query = breeze.EntityQuery.from(model.entitySets.document)
                              .where(predicate)
                              .expand("sections.items.cloudDriveFile, sections.cloudDriveFile")
                              .orderBy(model.orderByClauses.document);

    return _contextProvider.Context.Documents.Where(x => x.OrganisationId == currentUser.OrganisationId);

如果我在不加载任何“项目”的情况下编辑并保存“部分”,那么一切正常。但是,当我尝试编辑和保存具有“项目”的部分时——并且我已经加载了这些“项目”(使用 BreezeController 中的 Include 或 javascript 中的 Expand)——然后我收到以下错误:

“未捕获的TypeError:将循环结构转换为JSON”

我正在使用对 manager.saveChanges() 的简单调用进行保存。

我应该实施一些技术或模式来避免这种循环引用错误吗?

【问题讨论】:

    标签: json knockout.js breeze circular-reference


    【解决方案1】:

    不确定您的 EF 模型是 Code First 还是 Database First,但如果 Code First 我没有看到您的任何属性entityModel 与定义 ForeignKey 属性有关。如果数据库优先,请确保启用了外键关联。以下链接可能会提供更多信息:Navigation propertiesServer side model

    【讨论】:

    • 代码优先。您是说我必须在问题中显示的模型摘录中专门将 [ForeignKey] 属性添加到 ParentId 和 DocumentId 吗?我认为使用 Code First 命名约定(即 DocumentId 和 Document)就足够了。这是我在导航属性方面遇到的唯一问题,即那些不是自引用的似乎工作正常。
    • 一般来说,约定应该足够了,但是当涉及自引用约束时,如果没有 [ForeignKey] 属性,EF 可能无法正确确定 fk。当然值得一试。
    • 我已经添加了所有 ForeignKey 属性,但没有帮助。我已经能够进一步缩小范围,并用更多细节修改了我的问题。
    【解决方案2】:

    您可以通过预先加载子项来解决此问题。

    从公共虚拟列表子项中删除虚拟

    【讨论】:

    • 感谢您的建议 - 但这没有帮助。
    【解决方案3】:

    经过进一步调查,我发现每当我尝试将更改保存到已加载相关集合(即导航属性的内容)的对象时,都会出现同样的问题,然后集合中的对象有一个引用返回给父母。我在微风.debug.js(版本 1.3.5)中将错误跟踪到以下行:

    var bundle = JSON.stringify(saveBundle);
    

    我发现如果我将这一行替换为以下内容(根据JSON.stringify, avoid TypeError: Converting circular structure to JSON),则不再发生错误:

        var cache = [];
        var bundle = JSON.stringify(saveBundle, function (key, value) {
            if (typeof value === 'object' && value !== null) {
                if (cache.indexOf(value) !== -1) {
                    // Circular reference found, discard key
                    return;
                }
                // Store value in our collection
                cache.push(value);
            }
            return value;
        });
        cache = null; // Enable garbage collection
    

    虽然这解决了我当前的问题,但我觉得必须有另一种方法来解决这个问题 - 当然我不能是唯一一个试图在这种情况下保存更改的人。

    【讨论】:

    • 我以为我遇到了同样的问题,但这段代码并不能解决我的问题。有什么想法吗?
    • 事实证明,在我的情况下,cache.indexOf(value) !== -1 永远不会正确。
    猜你喜欢
    • 1970-01-01
    • 2018-10-05
    • 2016-01-22
    • 2017-06-29
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 2020-08-18
    相关资源
    最近更新 更多