Breeze не расширяет свойство навигации

У меня есть служба данных Breeze (он же datacontext) в моем одностраничном приложении. Я хочу получить список запусков от контроллера WebAPI вместе со списком OutlineItems для каждого запуска.

Контроллер возвращает список открытых запусков с дочерними элементами OutlineItem с помощью этого метода в BreezeController.

[AcceptVerbs("GET")]
public IQueryable<Run> Runs()
{
return _contextProvider.Context.Runs
    .Include("RunOutlineItems")
    .AsQueryable()
    .Where(r => r.RunStatusId < 4);    // 4 is the cutoff for open items             

}

Вот модель данных.

namespace PilotPlantBreeze
{
    public class Run
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Rundate { get; set; }
        public DateTime? RunStart { get; set; }
        public int MachineId { get; set; }
        public int ProductId { get; set; }
        public int RunStatusId { get; set; }
        public string Comments { get; set; }

        // Nav props
        public IList<OutlineItem> RunOutlineItems { get; set; }
    }
}       

Когда я смотрю на данные ответа из запроса WebAPI, список RunOutlineItems находится в JSON. Вот, например, один предмет:

{
    "$id":"27",
    "$type":"PilotPlantBreeze.OutlineItem,PilotPlantBreeze.Model",
    "Id":22,
    "RunId":5,
    "TankId":4,
    "OutlineTopicId":1,
    "OutlineDescriptionId":9,
    "PersonId":1,
    "Value":"23"
}

Вот мой код javascript на стороне клиента для получения данных из WebAPI. Проверка ошибок и проверка локального кеша опущены для ясности.

var getRuns = function () {
    // The EntityQuery is defined at the beginning of the dataservice
    //  Here I am asking for a query on the server.  Note the .expand 
    //  which is supposed to avoid lazy loading.  Lazy loading is turned off 
    //  on the WebAPI already.
    var query = EntityQuery
    .from("Runs")
    .expand("RunOutlineItems")
    .orderBy("rundate");

    // The manager is defined at the beginning of the dataservice
    //  Here I am asking the manager to execute the query with a promise
    return manager.executeQuery(query)
    .then(runsQuerySucceeded)
    .fail(runsQueryFailed);

    // The promise does not fail, but I would put an error in here if it ever does
    function runsQueryFailed(data) {
    }
    // When the promise succeeds, the data parameter is the JSON from the WebAPI
    function runsQuerySucceeded(data) {
        //
        // When I stop the debugger here data.results holds the entities, but
        //  the child entities for the RunOutlineItems is an observableArray with 
        //  nothing in it.
        //
        app.vm.runs.runs(data.results);
    }
};

Итак, мой вопрос заключается в том, как получить дочерние элементы в моей модели просмотра. У меня есть обходной путь, который получает дочерние элементы в отдельном вызове WebAPI на сервере и обрабатывает их с помощью пользовательского ko.bindHandler, но было бы удобно, чтобы работала технология навигации.


person bizcad    schedule 18.12.2012    source источник
comment
Пожалуйста, поставьте галочку под ответом Джея, если он ответил на ваш вопрос. Так мы будем знать, что вопрос закрыт. Если он не закрыт, сообщите нам, чтобы мы могли принять меры. Спасибо.   -  person Ward    schedule 20.12.2012


Ответы (1)


Вам не нужны как «включить» (на стороне сервера), так и расширить (на стороне клиента); любой из них должен сделать свое дело.

Поэтому я бы оставил запрос на стороне клиента в покое и изменил запрос на стороне сервера только на это:

[AcceptVerbs("GET")]
public IQueryable<Run> Runs() {
    return _contextProvider.Context.Runs
      .Where(r => r.RunStatusId < 4);    // 4 is the cutoff for open items             

}

Обратите внимание, что AsQueryable() также исчез.

Если это не сработает, отправьте сообщение обратно.

person Jay Traband    schedule 19.12.2012
comment
Это изменение по-прежнему не работает. Я изменил код сервера, как вы предложили, на следующее: var x = _contextProvider.Context.Runs .Where(r => r.RunStatusId ‹ 4); вернуть х; Когда я смотрю на правильно введенный x, свойство RunOutlineItems имеет значение null. Излишне говорить, что массив пуст и на клиенте. Поэтому я думаю, что мне нужен Include. Возможно, на клиенте мне нужно использовать EntityQuery.fromEntityNavigation, чтобы создать новый запрос и выполнить его, чтобы получить элементы навигации с сервера, когда я получу конкретный объект Run. Ник - person bizcad; 21.12.2012
comment
Попробуем детскими шажками. Верните включение в запрос на сервере и проверьте, включает ли результат EF дочерние элементы. Надеемся, что ваши навыки EF достаточно острые, чтобы вы могли проверить это в _contextProvider.Context при отладке кода сервера. Следующим шагом является проверка JSON по сети; вы должны увидеть их в теле ответа (используйте Fiddler или наблюдатель за сетью браузера среди его инструментов отладки). Мы ждем ваших выводов. - person Ward; 04.01.2013
comment
Я попробовал эти шаги. Я присвоил возвращаемое значение на сервере переменной var и IQueryable‹Run› и после проверки с помощью отладчика увидел, что Runs содержит дочерний элемент RunOutlineItem — это список. Я также вижу, что RunOutlineItem(s) находятся в теле ответа JSON на проводе. Я вижу их как в F12 с IE, так и в инструментах разработчика в Chrome. - person bizcad; 06.01.2013
comment
Когда обещание выполняется успешно, в функции выполняется выполнение запроса на выполнение (данные) { window.app.vm.runs.runs (data.results); };, остановлюсь на отладчике. data.XHR.responseText содержит RunOutlineItems, но data.results[0].runOutlineItems() имеет значение []. То же самое для data.results[1]...[n] - person bizcad; 07.01.2013
comment
Я не знаю, работает ли это с WebAPI - проверьте мой вопрос, который похож: stackoverflow.com/questions/17399906/ - person Rodney; 02.07.2013