Breeze多次查询一个knockout可观察数组

时间:2012-11-27 06:16:22

标签: knockout.js asp.net-mvc-4 breeze

我陷入了这一点,无法继续。

我正在以这种方式为搜索表单创建一个ViewModel:

var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
ko.applyBindings(viewModel);

稍后当用户点击查找按钮时,它会触发find方法(在此处简化):

self.Find = function (predicate) {
     var query = breeze.EntityQuery
         .from(self.actionName)
         .where(predicate);

     var promisse = self.manager.executeQuery(query)
          .then(querySucceeded)
          .fail(queryFailed);
 }

query *方法只将数据放在Knockout.js可观察数组中:

function querySucceeded(data) {
    data.results.forEach(function (item) {
        self.results.push(item);
    });

    return true;
}

function queryFailed(error) {
    var erroboj = { message: error.message };
    self.errors.push(erroboj);
    return false;
}

问题是,从不调用querySucceeded,并且Knockout.js的数据永远不会更新,因此会激活数据绑定。

我做错了什么?


这是ViewModel。有点不完整和模糊。 我想我没有正确理解微风查询的承诺:

/*global $, jQuery, ko, breeze, bootstrap */

function SearchViewModel(serviceName, actionName) {
    "use strict";
    var self = this;

    self.serviceName = serviceName;
    self.actionName = actionName;
    self.errors = ko.observableArray([]);
    self.results = ko.observableArray([]);

    self.CreateEntity = function (entityTypeName) {
        var entityType = self.manager.metadataStore.getEntityType(entityTypeName),
            newEntity = entityType.createEntity();
        return self.manager.addEntity(newEntity);
    };

    function querySucceeded(data) {
        // Here the function I want to run
        data.results.forEach(function (item) {
            self.results.push(item);
        });

        return true;
    }

    function queryFailed(error) {
        var erroboj = { message: error.message };
        self.errors.push(erroboj);
        return false;
    }

    function addError(errorMessage) {
        var erroobj = { message: errorMessage };
        self.errors.push(erroobj);
    }

    function NoFilterDefined(Condition) {
        var s = "Find(): Funcao Filter() not implemented:";
        addError(s);
        Condition = null;
        throw new Error(s);
    }

    try {
        self.Filter = NoFilterDefined;

        self.Find = function () {
            debugger;
            var Condition = breeze.Predicate;
            var predicate;

            self.errors.removeAll();
            try {
                predicate = self.Filter(Condition);
            } catch (errorf) {
                var sf = "Find(): Error calling Filter() in {actionName}: {error}";
                sf = sf.replace("{error}", errorf.message);
                sf = sf.replace("{actionName}", predicate.toString());
                addError(sf);
                throw new Error(sf);
            }

            var query = breeze.EntityQuery
                .from(self.actionName)
                .where(predicate);

            try {
                debugger;
                var promisse = self.manager.executeQuery(query)
                    .then(querySucceeded)
                    .fail(queryFailed);

                // Here I suppose the .then(querySucceeded) already was called
            } catch (errore) {
                var se = "Find(): Erro calling query in {actionName}: {error}";
                se = se.replace("{error}", errore.message);
                se = se.replace("{actionName}", self.actionName);
                addError(se);
                throw new Error(se);
            }
        };

        self.FetchMetadata = function () {
            //self.manager.fetchMetadata() // not working?
            //   .fail(self.queryFailed);
            var query = breeze.EntityQuery
                    .from(actionName)
                    .where("1", "==", "0"); // Just to get metadata

            var execution = self.manager.executeQuery(query);
            execution.then(function (data) {
                data = null;
            });
            return true;
        };

        self.SetParameters = function (parameters) {
            self.parameter = ko.observable(parameters);
        };

        self.store = new breeze.MetadataStore(); // define metadataStore for all managers
        self.manager = new breeze.EntityManager({
            serviceName: self.serviceName,
            metadataStore: self.store
        });

    } catch (error) {
        var erroboj = { message: error.message };
        self.Errors.push(erroboj);
    }
}

try {
    // Uncomment //debugger to debug this script. Use Visual Studio an IE to debug.
    //debugger;

    var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
    var parameter = {
        Id: "AAB-1113",
        Type: "CIF"
    };

    viewModel.SetParameters(parameter);

    viewModel.Filter = function (Condition) {
        "use strict";
        var self = this;
        var where = Condition.create("Type", "==", self.parameter.Type);

        if (parameter.Id !== null) {
            where = where.and("Id", "contains", self.parameter.Id);
        }

        return where;
    };

    ko.applyBindings(viewModel);

} catch (error) {
    alert("Erro de codigo:".concat(error.message));
}

1 个答案:

答案 0 :(得分:4)

最重要的问题:为什么你的querySucceeded方法根本没有被调用?我假设你的queryFailed也未被调用?应该击中一个或另一个。

您是否使用调试器验证了这两种方法都没有被调用?您确定服务器有任何查询结果吗?我将从网络流量日志中复制HTTP GET请求并在浏览器地址栏中重播它。只有在您确定服务器返回某些内容后,我才会继续处理查询结果。


注意:我刚看到问题陈述下方的完整ViewModel。

我在看到完整的VM之前写了我的回复,几乎重新开始。但我保留原来的答案,因为知道如何处理一个谜团很重要,而不仅仅是回答它。

问题几乎肯定与您的谓词有关。如果删除where(...)子句,我敢打赌你会看到结果。我敢打赌,谓词设置的条件永远不会成立,因此你永远不会有任何结果显示出来。

self.Find内,您将谓词初始化为Breeze Predicate构造函数。我认为你不想这样做。您可能想要创建一个新实例。

您似乎想要创建一个“身份条件” - 一个始终正确的条件。这对我来说似乎有点聪明。 NoFilterDefined的效用和实现对我来说也是一个谜......但现在我已经远离了眼前的事情。

为什么不让self.Filter()保持null直到有实际的过滤条件?然后适当地构建您的查询,可能如下:

var query = breeze.EntityQuery.from(self.actionName);
var predicate = self.Filter();
if (predicate) { query = query.where(predicate); }

结帐introduction to predicates


您的 querySucceeded 似乎应该可行,但我更喜欢一些更改。例如,我不会逐个将查询结果项推送到KO observableArray中。为什么不直接使用查询结果数组?

function querySucceeded(data) {
    self.results(data.results);
};

如果你担心在查询方法返回之前弄乱data.results数组的东西(为什么?),你可以先复制它

self.results(data.results.slice());

小点:

  • 我强烈建议将此类持久性问题从ViewModel移到辅助组件(例如dataservicedatacontext作为described here

    < / LI>
  • 据我所知,您不需要任何fetchMetadata业务。 Breeze在EntityManager的第一个查询中隐式获取元数据。您可以根据需要预先获取元数据(see MetadataStore.fetchMetadata),但这里没有明显需要。

  • 你的self.Find方法是否应该向调用者返回承诺?

  • 为什么您的querySucceeded会返回true

  • 您应该在执行查询之前清除self.results([])中的self.Find吗?我通常这样做。

  • 为什么self.errors中的queryFailed是一个KO observableArray。您正在将错误消息推送到错误消息数组...您在方法开头清除的数组。为什么一个阵列?为什么不能观察到简单的KO?