5

SPA アプリケーション (durandaljs) があり、取得するエンティティの「id」をマップする特定のルートがあります。

テンプレートは「/#/todoDetail/:id」です。

たとえば、「/#/todoDetail/232」または「/#/todoDetail/19」などです。

viewmodel の activate 関数でルート情報を取得するので、ID を取得できます。次に、breezejs EntityManager の新しいインスタンスを作成して、指定された ID を持つエンティティを取得します。

問題は、manager.fetchEntityByKey("Todos", id) を呼び出すと、EntityManager がサーバーからのメタデータをまだ持っていないため、「名前で「タイプ」を見つけることができません: 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);
    }
};
4

2 に答える 2

7

について学習しましfetchMetadataた。それは重要です。アプリケーションがクエリを発行せずに開始できる場合はfetchMetadata、キャッシュで直接操作を実行する前に、それを使用して戻るのを待つ必要があります (たとえば、データベース クエリにフォールバックする前に、キャッシュ内のキーでエンティティをチェックします)。 .

しかし、あなたが複数のマネージャーに言及したので、何か他のことが起こっているように感じます. デフォルトでは、新しいマネージャは他のマネージャのメタデータを知りません。しかし、単一の metadataStore を manager 間で共有できることをご存知ですか? あなたはできる。

私がよく行うこと (DocCode サンプルのメタデータ テストで確認できます) は、アプリケーションのメタデータ ストアを取得し、そのメタデータ ストアを使用して新しいマネージャーを作成する EntityManager ファクトリ関数を記述し、いつでもファクトリを使用することです。 m 新しいマネージャーを作成する ... ViewModel をスピンアップして TodoDetail を確認するときに行っているようです。

于 2013-02-11T06:49:42.427 に答える
2

Silverlight のバックグラウンドを持ち、Caliburn Micro と組み合わせて多くの WCF RIA サービスを使用した経験から、Breeze と Durandal を統合するためにこのアプローチを使用しました。

アプリケーションの App フォルダーに services というサブフォルダーを作成しました。そのフォルダーに、datacontext.js という JavaScript ファイルを作成しました。ここに私のデータコンテキストのサブセットがあります:

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)
        }
    };
}

次に、デュランダル ビュー モデルで、サービス/データ コンテキストを要求するだけです。たとえば、これは私のアプリのサンプル ビュー モデルの一部です。

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;
});

これにより、すべてが 1 か所で行われるため、すべてのビュー モデルでメタデータ ストアを初期化することについて心配する必要がなくなります。

于 2013-02-11T17:20:19.687 に答える