1

I have a DbDataController which delivers a List of Equipment.

    public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
        var q= DbContext.EquipmentSet.OrderBy(e => e.Name);
        return q;
    }

In my scaffolded view everything looks ok.

But the Equipment contains a HashSet member of EquipmentType. I want to show this type in my view and also be able to add data to the EquipmentType collection of Equipment (via a multiselect list).

But if I try to include the "EquipmentType" in my linq query it fails during serialisation.

    public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
        var q= DbContext.EquipmentSet.Include("EquipmentType").OrderBy(e => e.Name);
        return q;
    }

"Object Graph for Type EquipmentType Contains Cycles and Cannot be Serialized if Reference Tracking is Disabled"

How can I switch on the "backtracking of references"?

Maybe the problem is that the EquipmentType is back-linking through a HashSet? But I do not .include("EquipmentType.Equipment") in my query. So that should be ok.

How is Upshot generating the model? I only find the EquipmentViewModel.js file but this does not contain any model members.

Here are my model classes:

public class Equipment
{
    public Equipment()
    {
        this.Exercise = new HashSet<Exercise>();
        this.EquipmentType = new HashSet<EquipmentType>();
        this.UserDetails = new HashSet<UserDetails>();
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Picture { get; set; }
    public string Link { get; set; }
    public string Producer { get; set; }
    public string Video { get; set; }

    public virtual ICollection<EquipmentType> EquipmentType { get; set; }
    public virtual ICollection<UserDetails> UserDetails { get; set; }
}
public class EquipmentType
{
    public EquipmentType()
    {
        this.Equipment = new HashSet<Equipment>();
        this.UserDetails = new HashSet<UserDetails>();
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Equipment> Equipment { get; set; }
    public virtual ICollection<UserDetails> UserDetails { get; set; }
}
Obiwan007
  • 646
  • 1
  • 8
  • 20

4 Answers4

2

try decorating one of the navigation properties with [IgnoreDataMember]

[IgnoreDataMember]
public virtual ICollection<Equipment> Equipment { get; set; } 
Joe
  • 83
  • 6
  • Not possible because the datamodel classes are dynamically created from the edmx model through templating... I was able to solve the issue via using a DTO POCO class which does not contain the backreference. Unfortunately the scaffolding must be tricked in using the "real model" and then the controller and view changed to use the DTO which is not held by the database at all. Posting back to the DB is done manually then in the DbController handling members - without using the DbContext and Update/delete Handlers as they could not deal with the DTOs either of cause. – Obiwan007 Mar 26 '12 at 19:36
0

To solve the cyclic backreference, you can use the IgnoreDataMember attribute. Or you can set the back reference to NULL before returning the data from the DbDataController

I posted a working solution to your problem in a different question, but using Entity Framework Code First. https://stackoverflow.com/a/10010695/1226140

Here I show how to generate your client-side model manually, allowing to you to map the data however you please

Community
  • 1
  • 1
Bart Jolling
  • 595
  • 6
  • 21
  • What would one do if he in one case uses the navigation one way, and in a nother case he uses it the other way. IgnoreDataMember will only let it work one way? – Poul K. Sørensen Oct 17 '12 at 10:01
0

The model generated by upshot can be found on the page itself. In your Index view you will see the UpshotContext HTML helper being used (given that you are using the latest SPA version), in which the dataSource and model type are specified.

When the page is then rendered in the browser, this helper code is replaced with the actual model definition. To see that, view the source code of your page in the browser and search for a <script> tag that starts with upshot.dataSources = upshot.dataSources || {};

Check here for more info about how upshot generates the client side model. As for the "backtracking of references", I don't know :)

Community
  • 1
  • 1
Szilard Muzsi
  • 1,881
  • 2
  • 16
  • 20
  • Yes, the model classes are located in the Scripts folder - probably through the UpshotContext class. Thats working fine. One problem is - you see only the Viewmodel classes there - not the actual generated classes which seems to be dynamically created via the dataSource function. – Obiwan007 Mar 21 '12 at 19:11
0

I figured out - partially how to solve the circular reference problem.

I just iterated over my queried collection (with Include() ) and set the backreferences to the parent to NULL. That worked for the serialisation issue which otherwise already breaks on the server.

The only problem now is the update of a data entity - its failing because the arrays of the referenced entitycollection are static...

Obiwan007
  • 646
  • 1
  • 8
  • 20