0

I am trying to build an array of entities from a server query that exist in an object arrays

The diagram below illustrates my model:

Entity model

In my datacontext, I've applied the following code:

function getByDboardConfig(dboardConfig) {
        var busUnitDims = [];
        var busUnitsTotalCount = dboardConfig.busUnits.length;
        var buCount = 0;

        dboardConfig.busUnits.forEach(function (busUnit) {
            eq.from('BusUnitDimensions') // eq = breeze.EntityQuery
                .where('busUnitId', '==', busUnit.id)
                .using(em).execute() // em = EntityManager
                .to$q(succeeded, failed); // using Angular, thus to$q
        });

        function succeeded(data) {
            buCount++;
            data.results.forEach(function (result) {
                busUnitDims.push(result);
            });

            if (buCount === busUnitsTotalCount) {
                console.log(busUnits.length);  
                return busUnitDims;
            }
        }
    }

When I log to the console as show the length of the array, I get the correct entity count, but when I return the result of this call to my controller I get undefined. Not understanding why?

I've tried returning $q.when(busUnitDims) as well but I still get undefined.

zpydee
  • 4,487
  • 4
  • 16
  • 19
  • I'm hypothesising that I'm somehow not returning a promise. Could this be? – zpydee Feb 08 '14 at 11:18
  • 1
    Your getByDboardConfig() function is not returning anything at all? (Notice that the value succeeded return never gets propagated to your controller, as it's one scope below). – SveinT Feb 08 '14 at 11:34
  • @SveinT Thanks for your comment. Yes, I've noticed that if I add `return busUnitDims` outside the succeeded function's scope, my controller does get the return, but sometimes it returns 0 results, sometimes the result after forEach iteration 1 and sometimes the result after iteration 2. Can you offer any enhancements to make this more stable? – zpydee Feb 08 '14 at 11:43
  • If you want to return the actual object and not a promise for it than you must ensure all promises are resolved before returning. And you do need to actually return a value from getByDboardConfig - you are not doing that at the moment. You could create an array of promises with forEach and only return after $q.all(promisesArray) is resolved. – user2847643 Feb 08 '14 at 14:48
  • Aren't you supposed to console.log(busUnitDims.length) instead of console.log(busUnits.length)? Pls check the result then reply to me – Adel Sal Feb 08 '14 at 22:47
  • @AdelSal Apologies, that was just a typo in the SO code snippet. I am logging `busUnitDims.length` and it returns the correct value – zpydee Feb 09 '14 at 10:49
  • @daveb73 That's fine.. Please check my answer bellow – Adel Sal Feb 09 '14 at 21:05

1 Answers1

1

The problem with your code is that the function is not returning anything, even if you relocate the return line outside the succeeded block , it may return before filling the array is finished(notice you're executing the query asynchronously )

Neverthless, looking at your code; I take it you are getting the busUints and then query for each of their line items BusUnitDimensions separately; that could mean many roundtrips to the server.

Anyways, you aim to fetching busUnits along with their related BusUnitDimensions (eager loading).

Although you didn't provide an idea of how your view model or your controller looks like; I assume you have one view for DboardConfig and another view for both related busUnits and BusUnitDimensions

so your workflow is:

  1. Get a list of DboardConfigs
  2. for each DboardConfig, load it's busUnits along with BusUnitDimensions

Hence, your function could be :

function getByDboardConfig(dboardConfig) {
   return  eq.from("busUnits")
    .where("dboardConfigId", "==", dboardConfig.id)
    .expand("BusUnitDimensions")
    .using(em).execute() // em = EntityManager

Then inside your controller:

   $Scope.getBusUnitsandDimentions = function () {
    dataservice.getByDboardConfig($Scope.dboardConfig)
        .then(succeeded)
        .fail(failed);
};

    function succeeded(data) {
       $Scope.busUnits = [];
        data.results.forEach(function (result) {
            $Scope.busUnits.push(result);
        });
        }
    }
}

This way, you can remove the coding for fetching busUnits since we've already fetched it with it's related child table.

Simply put:

  1. busUnits to get your array of bus units for a specified DboardConfig
  2. busUnits.BusUnitDimensions to get it's related dimensions
Adel Sal
  • 718
  • 5
  • 16
  • Thanks. Give me a chance to study this in the context of my application and I'll give you some feedback thereafter. – zpydee Feb 10 '14 at 09:43
  • you're welcome. Please take a look at Breeze documentation in case you're planning to enhance it with caching http://www.breezejs.com/documentation/navigation-properties – Adel Sal Feb 10 '14 at 14:54
  • Perhaps you'd be interested in also taking a look at [***this question***](http://stackoverflow.com/questions/21679073/entity-framework-object-graph-deletion-with-breeze), which deals with deleting object graphs. I've read elsewhere that Breeze doesn't support cascaded deletes, but if you read my question, you'll notice some strange observations. – zpydee Feb 10 '14 at 15:13
  • That's my friend, is another issue..Anyway, I've answered that too.:) – Adel Sal Feb 10 '14 at 20:09