Breezejs EntityManager MetadataStore和fetchEntityByKey

时间:2013-02-10 23:00:45

标签: breeze durandal

我有一个SPA应用程序(durandaljs),我有一个特定的路由,我映射我想要获取的实体的“id”。

模板是“/#/ todoDetail /:id”。

例如,“/#/ todoDetail / 232”或“/#/ todoDetail / 19”。

在viewmodel的activate函数中,我获取路由信息,以便我可以获取id。然后我创建了一个breezejs EntityManager的新实例来获取具有给定id的实体。

问题是当我调用manager.fetchEntityByKey(“Todos”,id)时,EntityManager还没有来自服务器的元数据,因此抛出异常“无法通过名称找到'Type':Todos ”。

只有在调用fetchEntityByKey之前首先对存储(manager.executeQuery)执行查询时,它才有效。

这是预期的行为还是错误?在实例化EntityManager期间有没有办法自动生成元数据?

注意:我认为在我的情况下很难使用共享的EntityManager,因为我想允许用户直接在浏览器上键入路由。

编辑:作为临时解决方法,我这样做:

BreezeService.prototype.get = function (id, callback) {
    var self = this;

    function queryFailed(error) {
        app.showMessage(error.message);
        callback({});
    }

    /* first checking if metadatastore was already loaded */

    if (self.manager.metadataStore.isEmpty()) {
        return self.manager.fetchMetadata()
        .then(function (rawMetadata) {
            return executeQuery();
        }).fail(queryFailed);
    } else {
        return executeQuery();
    }

    /* Now I can fetch */
    function executeQuery() {
        return self.manager.fetchEntityByKey(self.entityType, id, true)
                        .then(callback)
                        .fail(queryFailed);
    }
};

2 个答案:

答案 0 :(得分:7)

您已了解fetchMetadata。这很重要。如果应用程序可以在不发出查询的情况下开始,则必须使用fetchMetadata并等待它返回,然后才能直接在缓存上执行任何操作(例如,在退回之前通过缓存中的键检查实体到数据库查询)。

但我感觉到其他事情正在发生,因为你提到了多个经理人。默认情况下,新管理员不知道来自任何其他经理的元数据。但是你知道吗你可以在经理之间共享一个元数据商店吗?你可以。

我经常做的(你会在DocCode示例的元数据测试中看到它),获取应用程序的metadataStore,编写一个EntityManager工厂函数,用该metadataStore创建新的管理器,然后使用工厂每当我创建新经理时...就像你在启动ViewModel以查看TodoDetail时所做的那样。

答案 1 :(得分:2)

来自Silverlight背景,我使用了很多WCF RIA服务和Caliburn Micro,我使用这种方法将Breeze与Durandal集成在一起。

我在应用程序的App文件夹中创建了一个名为services的子文件夹。在该文件夹中,我创建了一个名为datacontext.js的javascript文件。这是我的datacontext的一个子集:

define(function (require) {

    var breeze = require('lib/breeze'); // path to breeze
    var app = require('durandal/app');  // path to durandal

    breeze.NamingConvention.camelCase.setAsDefault();

    // service name is route to the Web API controller
    var serviceName = 'api/TeamData',

    // manager is the service gateway and cache holder
    manager = new breeze.EntityManager(serviceName),

    store = manager.metadataStore;

    function queryFailed(error) {
        app.showMessage("Query failed: " + error.message);
    }

    // constructor overrides here

    // included one example query here
    return datacontext = {
        getSponsors: function (queryCompleted) {
            var query = breeze.EntityQuery.from("Sponsors");
            return manager
                .executeQuery(query)
                .then(queryCompleted)
                .fail(queryFailed)
        }
    };
}

然后在您的durandal视图模型中,您可以只需要services / datacontext。例如,以下是我的应用程序中的示例视图模型的一部分:

define(function (require) {

    var datacontext = require('services/datacontext');

    var ctor = function () {
        this.displayName = 'Sponsors',
        this.sponsors = ko.observable(false)
    };

    ctor.prototype.activate = function () {
        var that = this;
        return datacontext.getSponsors(function (data) { that.sponsors(data.results) });
    }

    return ctor;
});

这将使您不必担心在每个视图模型中初始化元数据存储,因为它全部在一个地方完成。