breeze

Only getting one child observable when I retrieve complete objects graph


I have a large object graph that I want to return to the client (an overview of the entire model) so I decided to send it back as one big object (I'm returning it as the object in question.)

In Breeze however I'm only getting the first object in each dependent object. So for example I have a 'policy' object with two 'vehicle' objects. I only see one vehicle (even when I put a breakpoint at var p = data.results[0]. The json coming back from the call shows two vehicles but breeze is catching only one.

What can I do to get the other ones? Here's the call I'm making:

var getPolicyByPolicyNumber = function (lob, policynumber, policyObservable) {

    var params = {};
    params['lOBCd'] = lob;
    params['policyNumber'] = policynumber;

    var query = EntityQuery.from('PolicyInquiry')
        .withParameters(params);


    return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

    function querySucceeded(data) {
        var p = data.results[0];
        p.completeTree(true);

        return policyObservable(p);

    }

};

And in my breeze controller I have the following:

[System.Web.Http.HttpGet]
public Policy PolicyInquiry(string lOBCd, string policyNumber)
{
    UserProfile userProfile = _contextProvider.Context.UserProfiles.SingleOrDefault(u => u.UserName == WebSecurity.CurrentUserName);
    var policy = Uow.PolicyServices.GetPolicy(userProfile.BrokerId, userProfile.AgencyId, "csio:" + lOBCd, policyNumber);
    return policy;
}

And here's an abbreviated model showing policy and vehicle:

public class Policy
{
    public int Id { get; set; }
    public string PolicyNumber { get; set; }

    [InverseProperty("Policy")]
    public ICollection<Vehicle> Vehicles { get; set; }

    // other fields removed
}

public class Vehicle
{
    public int Id {get; set}
    public string ItemId { get; set; }
    // other fields removed

    //Foreign Keys
    public int PolicyId { get; set; }
    [IgnoreDataMember]
    [ForeignKey("PolicyId")]
    [Required]
    public virtual Policy Policy { get; set; }
}

Solution

  • Now that I see your model I think I see the issue.

    Breeze does not automatically resolve the entity graph on a query. i.e. if you retrieve a Policy, Breeze only returns the Policy instance itself without any navigation properties resolved. This is by design, so that a single query doesn't bring down the entire entity graph.

    If you want the values of any navigation properties you have three options, the third of which is probably your best bet. I've taken some liberties in simplifying your model for the purposes of explanation. These all assume that the "Policy" type is actually defined as a Breeze entity type, i.e. has a metadata definition in the Breeze metadataStore.

    1. Use an client side EntityQuery.expand clause

      var query = EntityQuery.from('Policy')
                             .expand("Vehicles")
                             .withParameters(params);
      
    2. Use a server side Include clause

      [System.Web.Http.HttpGet]
      public IEnumerable<Policy>(string lOBCd, string policyNumber) 
      {
          return _contextProvider.Context.Policies
                                         .Where(....)
                                         .Include("Vehicles");
      }
      
    3. Use a anonymous result, that contains two known entity types.

      [System.Web.Http.HttpGet]
      public Object PolicyInquiry(string lOBCd, string policyNumber)  
      {
          UserProfile userProfile = _contextProvider.Context
                                                    .UserProfiles
                                                    .SingleOrDefault(u => u.UserName == WebSecurity.CurrentUserName);
      
          var policy = Uow.PolicyServices.GetPolicy(userProfile.BrokerId, userProfile.AgencyId, "csio:" + lOBCd, policyNumber);
      
          return new  
                 { 
                     Policy = policy, 
                     Vehicles = policy.GetVehicles() // ensure that they are actually resolved on the server)
                 }
      
          return policy;
      }
      

    More info here: Navigation Properties

    I hope this is clear enough.