Breezejs Uncaught TypeError:将循环结构转换为JSON

时间:2013-06-18 01:43:13

标签: json knockout.js breeze circular-reference

我有一个使用Hot Towel模板的ASP.Net MVC SPA,即breezejs,knockout,实体框架(代码优先),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);

如果我编辑并保存“部分”而不加载任何“项目”,那么一切正常。但是当我尝试编辑并保存一个包含“Items”的部分时 - 我已经加载了那些“Items”(使用BreezeController中的Include或javascript中的扩展) - 然后我收到以下错误:

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

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

我是否应该采用一些技术或模式来避免这种循环引用错误?

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

您可以通过急切加载儿童来解决此问题。

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

答案 2 :(得分:0)

经过进一步调查后,我发现每当我尝试将更改保存到已加载相关集合的对象(即导航属性的内容)时,就会发生同样的问题,其中集合中的对象随后返回参考到了父母。我将错误跟踪到breeze.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

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