Question

I have an ASP.Net MVC SPA using the Hot Towel template i.e. breezejs, knockout, entity framework (code first), durandal etc.

In my EF model I have a class named "Section" that has a self referencing association. Each section belongs to a "Document" and each Section also has a collection of "Items":

    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; }

       ...
   }

I load the "Sections" and "Items" when I load the documents via a Breeze query and a BreezeController method:

    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);

If I edit and save a "Section" without loading any "Items" then all works OK. However when I try to edit and save a section that has "Items" - and I have loaded those "Items" (either using an Include in the BreezeController or an Expand in javascript) - then I get the following error:

"Uncaught TypeError: Converting circular structure to JSON "

I am saving using a simple call to manager.saveChanges().

Is there some technique or pattern that I should be implementing to avoid this circular reference error?

Was it helpful?

Solution 3

After further investigation I found that this same problem was occurring whenever I tried to save changes to an object that had loaded a related collection (i.e. the contents of a navigation property), where the objects in the collection then had a reference back to the parent. I tracked the error down to the following line in breeze.debug.js (version 1.3.5):

var bundle = JSON.stringify(saveBundle);

I found that if I replaced this line with the following (as per JSON.stringify, avoid TypeError: Converting circular structure to JSON) then the error no longer occurred:

    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

While this fixes my current issue I feel that there must be an alternative approach to this - surely I cannot be the only one trying to save changes in this scenario.

OTHER TIPS

Not sure if your EF model is Code First or Database First, but if Code First I didn't see any attributes on your entityModel having to do with defining the ForeignKey property. If Database First make sure that foreign key associations are enabled. The following links may provide more information: Navigation properties, Server side model

You might be able to fix this issue by eager loading the Children instead.

Remove the virtual from public virtual List Children

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top