2013-02-10 6 views
5

私はSPAアプリケーション(durandaljs)を持っています。フェッチしたいエンティティの "id"をマップする特定のルートがあります。Breezejs EntityManager MetadataStoreとfetchEntityByKey

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

たとえば、「/#/ todoDetail/232」または「/#/ todoDetail/19」と入力します。

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

問題は、manager.fetchEntityByKey( "Todos"、id)を呼び出すときにEntityManagerがサーバーからのメタデータをまだ持っていないため、例外をスローしています "名前で 'Type'を見つけることができません:トドス "。

最初にfetchEntityByKeyを呼び出す前に、ストア(manager.executeQuery)に対してクエリを実行した場合にのみ機能します。

これは予期しない動作またはバグですか? EntityManagerのインスタンス化中にメタデータをオートフェッチする方法はありますか?

注:ユーザーがブラウザに直接ルートを入力できるようにするため、私のケースでは共有EntityManagerを使用するのは難しいと思います。

EDIT:一時的な回避策として、私はこれをやっている:あなたはおよそfetchMetadataを学んだ

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

答えて

7

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

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

私はしばしば(DocCodeサンプルのメタデータテストで参照してください)、アプリケーション用のmetadataStoreを取得し、そのメタデータストアで新しいマネージャを作成するEntityManagerファクトリ関数を記述してから、あなたがTodoDetailをレビューするためにViewModelを回転させたときにあなたがやっているように、私は新しいマネージャーをつくっています。

+0

sugestionが良いので、ファクトリを持つentityManagersを作成し、それらの間でグローバルにメタデータを共有します。ところで、この施設を追加するために風を改善する機会はありますか?メタデータの世界的な例のようですか?または、サービスに対して完全なクエリを実行せずにentityManagerにfetchEntityByKeyだけを要求してもメタデータをクエリするように強制しますか? –

+0

あなたは何を意味するのかよく分かりません。私はBreezeで定義されたデフォルトのMetadataStoreに熱心ではありませんが、それは自分で簡単に作成できるものです。 MetadataStoreにfetchMetadata(これはもちろん非同期)をクエリとは別のものにすることができます(私の答えでこれを述べました)。また、 'EntityManager.createEmptyCopy'を見るかもしれません。マスターEMでそれを呼び出すと、完全に構成された新しい空のEMを作成できます。残りのファクトリメソッドは、コピーから必要なエンティティ(参照リストなど)だけをマスターからインポートします。 – Ward

2

多くのWCF RIAサービスとCaliburn Microを使用したSilverlightの背景から、私は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) 
     } 
    }; 
} 

は、その後、あなたのデュランダルビューモデルで、あなたは、サービス/ 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; 
}); 

これは、あなたはそれがすべて一つの場所で行われているので、すべてのビューモデルにメタデータストアの初期化を心配しないようになります。

+0

Silverlight/Caliburn.MicroとWCF Ria Servicesについての背景もあります。実際には、MVCのバンドルを使用している場合、バンドルされたスクリプトにbreeze.min.jsを含めることができ、require( 'path/to/breeze')を呼び出す必要はありません。私の[durandal video](http://www.youtube.com/watch?feature=player_embedded&v=in1M0vzg4mg)を参照してください。私の問題は、最初にクエリを実行せずにメタデータを欲しいということです。ありがとう! –

+0

私は単一のエンティティを取得するためにクエリを使用していたので、それは私のために働いたと思います。 var query = breeze.EntityQuery.from( "AthleteDetails")。ここで( "Id"、 "=="、id); – Bryant

+0

はい、EntityQueryを使用すると、マネージャが以前にフェッチしていない場合にメタデータをフェッチするクエリが実行されているため、クエリの結果がエンティティの配列になるため、ゼロインデックスでアクセスする必要がありますresult.entities [0]のように。必要な場合は、キャッシュからエンティティを返すこともできますが、マネージャのメタデータを取得しないで、手動でフェッチしないと例外がスローされます(fetchEntityByKey()は例外です)質問に。 –

関連する問題