0
votes

I am using the latest versions of Angular, breeze, EF.

I am constructing a complex object on a client called a Quote which is added to a job. This has a QuoteMeasure added to it. One of the properties of QuoteMeasure is a navigation property called measure:

var quote = em.createEntity("Quote", { id: breeze.core.getUuid() }),
quoteMeasure,
measure;
measure = _getMeasureFromLookups(4);
quoteMeasure = em.createEntity("QuoteMeasure", { id: breeze.core.getUuid(), quoteId: quote.id });

I have tried the following which executes a query to the server

quoteMeasure.measureId = measure.id;
quoteMeasure.entityAspect.loadNavigationProperty("measure").then(function () {
    console.log(quoteMeasure.measure);
});
quote.quoteMeasures.push(quoteMeasure);
job.quotes.push(quote);

to url /Breeze/Data/Measure?$filter=Id%20eq%204&

which does not exist. I would ideally like to set the navigation property manually as it is static data and previously obtained from a breeze query lookups on the server:

    [HttpGet]
    public object Lookups()
    {
        var measures = UnitOfWork.MeasureRepository.Get(null, q => q.OrderBy(m => m.Ordinal)).ToList();
        return new { measures = measures };
    }

This is what the function _getMeasureFromLookups does, it looks up the previously stored measure. I would like to do assign it this way:

quoteMeasure.measure = measure;

But I get the following meaningless error on the client:

Error: A is undefined M@//llhst/X/Scripts/breeze.min.js:1 d/f.set@//llhst/X/Scripts/breeze.min.js:5 _createNewQuote@//llhst/X/Scripts/app/services/jobService.js:76

This I assume is because a full tree of objects has been downloaded via the lookup rather than an individual measure entity. In http://www.breezejs.com/documentation/navigation-properties there is a section on 'Omitting navigation properties' but then it neglects to tell you how to do this.

So my question is what is best practise for loading navigation property data offline? How can I modify the sample above so that it works?

3

3 Answers

1
votes

If I understand your requirement correctly, you should be able to construct your quote and quoteMeasure entities as follows:

var quote = em.createEntity("Quote", { id: breeze.core.getUuid() });

//the assignment quoteId: quote.id is the same as quote.quoteMeasures.push(quoteMeasure)
//you don't need to add it again to the collection
var quoteMeasure = em.createEntity("QuoteMeasure", { id: breeze.core.getUuid(), quoteId: quote.id });

var measure = _getMeasureFromLookups(4);

quoteMeasure.measure = measure;

//or
//quoteMeasure.measureId = measure.id

//your _getMeasureFromLookups should look something like this
function _getMeasureFromLookups(measureId) {
  //getEntityByKey will look up Measure from client cache
  return em.getEntityByKey('Measure', measureId);
}

Calling loadNavigationProperty will initiate a query to the server.

The 'Omitting navigation properties' section actually tells you how you can omit the principal side of the association. So for example, to apply it to your EF model, if you don't want a Quote to be able to navigate to all QuoteMeasures, you can do the following:

//EF Model on Server
public class Quote {

  //Simply remove or comment this collection navigation property
  //public virtual ICollection<QuoteMeasure> QuoteMeasures { get; set; }
}

Hope this helps.

1
votes

Seems the problem was the ommission of these statements:

        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = false;

Not having this caused the preloading of not only the navigation properties but all of theirs as well which caused the obscure error I noted above. No other modifications were required to get the code working.

0
votes

EntityAspect.loadNavigationProperty() always makes a request to the server. If you want properties be loaded without making a separate request, do Eager loading with EF.

If you have several properties which are null when breeze fetches them, and you don't want to make several loadNavigationProperty calls, use EntityQuery.expand() method. You can list any properties you need to be loaded