10

ExtJS 4.1.0

2013 年 6 月 6 日更新:

これと同じ質問を Sencha フォーラムに投稿しましたが、あまりアクションはありませんでした。投稿はほぼ同じですが、参照用にここに追加すると思いました。ExtJS アプリケーションの非常に一般的なシナリオについて、他のコミュニティ メンバーの意見を聞きたいと思っています。 http://www.sencha.com/forum/showthread.php?265358-Complex-Model-Save-Decoupling-Data-and-Updating-Related-Stores

2013 年 7 月 16 日更新 (結論?)

Sencha の投稿は、ほとんど議論を集めませんでした。複雑な保存操作の負荷の大部分をアプリケーション サーバーに置き、必要に応じてクライアント ストアを遅延更新することにしました。このようにして、独自のデータベース ラッパーを使用して、1 つの複雑なドメイン オブジェクトの保存に関連付けられたすべてのトランザクションを包含し、原子性を保証することができます。新規Orderの保存が、注文メタデータ、10 個の新しいインスタンス、OrderContentsおよび潜在的に他の情報 (他のテーブルに存在する住所、注文作成時に定義された新しい顧客など) の保存で構成されている場合、ペイロードをアプリケーションに送信したいと思います。クライアント側のアプリケーション コードで下品なコールバックの Web を確立するのではなく、サーバーを使用します。1 対 1 で関連付けられているデータ ( OrderhasOneなどAddress) は、success操作のコールバックOrder.save()。のコンテンツなどのより複雑なデータは、Orderを呼び出すだけで遅延処理されますcontentStore.sync()これは、圧倒的な数のクライアントコールバックなしで原子性を保証する手段だと思います

元の投稿内容

関連付けが多いモデルを保存するという全体的に期待外れの機能を考えると、私は自分のアプリケーションでモデルの関連付けをほとんど捨てて、関連付けられたデータを自分で取得することに頼っています。これはすべて問題ありませんが、残念ながら、実際にデータを保存し、ExtJS ストアを更新してサーバー上の変更を反映するという問題は解決されません。

たとえば、メタデータと注文の部品でOrder構成されるオブジェクトの保存を考えてみましょう。OrderContentsメタデータOrder_Dataはデータベースのテーブルに格納されますが、コンテンツはすべて、Order_Contents各行が列を介して親注文にリンクされているテーブルに格納されorder_idます。

クライアントでは、注文のコンテンツを取得することは、関連付けを必要とせずに非常に簡単に行うことができます: var contents = this.getContentsStore().query('order_id', 10).getRange(). ただし、主な欠陥は、これがExtJS Storeで利用可能なコンテンツ レコードにOrderContents依存していることです。これは、データ サーバーによって返されない関連付けを「メイン」オブジェクトと使用している場合に適用されます。

注文を保存するとき、注文のメタデータ (日付、注文番号、サプライヤー情報など) とコンテンツの配列を保持する単一の要求を送信します。これらのデータはバラバラに選択され、適切なテーブルに保存されます。これは私にとって十分に理にかなっており、うまく機能します。

アプリケーションサーバーから保存/更新されたレコードを返すまでは、すべて問題ありません。リクエストは を呼び出すことによって開始されるため、ストアに新しいレコードが利用可能であることOrderObject.save()を伝えるものは何もありません。OrderContents代わりに store にレコードを追加して を呼び出すと.sync()、これは自動的に処理されますが、これにより保存プロセスが複雑になると感じており、言うまでもなく、アプリケーションサーバーでこの分離を処理したいと思います。リクエスト全体を保存することは非常に優れています同じように。

これを解決するより良い方法はありますか?私の現在の解決策は次のとおりです...

var orderContentsStore = this.getOrderContentsStore();
MyOrderObject.save({
    success: function(rec, op){
        // New Content Records need to be added to the contents store!
        orderContentsStore.add(rec.get('contents')); // Array of OrderContent Records
        orderContentsStore.commitChanges(); // This is very important
    }
});

ストアに追加されたレコードを呼び出すことによりcommitChanges()、クリーン (非ファントム、非ダーティ) と見なされるため、ストアのgetModifiedRecords()メソッドによって返されなくなります。当然のことながら、store.sync().

このアプローチは、ちょっとずさんでハックなように思えますが、より良い解決策を見つけていません...

ご意見やご感想をお待ちしております。

4

1 に答える 1

3

2013 年 8 月 26 日に更新関連データは、モデルのプロキシの create/update コールバックで Ext によって実際に処理されることがわかりましたが、そのデータを見つけるのは簡単ではありませんでした。 Model.Save() レスポンス

さて、この質問を開いてから数か月が経ちましたが、この問題に対する魔法のように素晴らしい解決策はないように感じます.

私の解決策は次のとおりです...

複雑なモデル (たとえば、いくつかの関連付けがある、またはいくつかのhasMany関連付けを持つモデル) を保存する場合、すべての関連付けられたデータを含む「親」モデルを保存し (モデルのプロパティ/フィールドとして!)、(保存された) afterSave/afterUpdate コールバックの関連データ。

たとえば、私のPurchaseOrderモデル whichhasMany ItemshasOne Address. モデルの関連付けストアにのみ存在する場合、関連付けられたデータはサーバーに渡されないため、関連付けられたデータはモデルのプロパティに含まれていることに注意してください。

console.log(PurchaseOrder.getData());
---
id: 0
order_num: "PO12345"
order_total: 100.95
customer_id: 1
order_address: Object
    id: 0
    ship_address_1: "123 Awesome Street"
    ship_address_2: "Suite B"
    ship_city: "Gnarlyville"
    ship_state: "Vermont"
    ship_zip: "05401"
    ...etc...
contents: Array[2]
    0: Object
        id: 0
        sku: "BR10831"
        name: "Super Cool Shiny Thing"
        quantity: 5
        sold_price: 84.23
    1: Object
        id: 0
        sku: "BR10311"
        name: "Moderately Fun Paddle Ball"
        quantity: 1
        sold_price: 1.39

と についてModels確立しましPurchaseOrder.ContentたがPurchaseOrder.Address、 のデータPurchaseOrderはこれらのモデルのインスタンスではなく、単なるデータです。繰り返しますが、これはアプリケーション サーバーに正しく渡されるようにするためです。

上記のようなオブジェクトを取得したら、.save()次のようにアプリケーション サーバーに送信します。

PurchaseOrder.save({
    scope: me,
    success: me.afterOrderSave,
    failure: function(rec,op){
        console.error('Error saving Purchase Order', op);
    }
});

afterOrderSave: function(record, operation){
    var me = this;
    switch(operation.action){
        case 'create':
            /** 
              * Add the records to the appropriate stores.
              * Since these records (from the server) have an id,
              * they will not be marked as dirty nor as phantoms 
              */
            var savedRecord = operation.getResultSet().records[0];  // has associated!
            me.getOrderStore().add(savedRecord);
            me.getOrderContentStore().add(savedRecord.getContents()); //association!
            me.getOrderAddressStore().add(savedRecord.getAddress()); // association!
            break;

        case 'update':
            // Locate and update records with response from server
            break;
    }
}

私のアプリケーションサーバーは を受け取り、PurchaseOrderそれに応じてデータの保存を処理します。このプロセスは独自の実装に大きく依存するため、大まかな詳細については説明しません。私のアプリケーション フレームワークは大まかに Zend 1.11 に基づいています (主に を利用していますZend_Db)。

以下の理由から、これが最善の方法だと思います。

  • クライアント上のさまざまな model.save() コールバックの乱雑な文字列はありません
  • 管理が非常に簡単な 1 つの要求のみ
  • 原子性はアプリケーションサーバーで簡単に処理できます
  • 往復が少ない = 心配する潜在的な障害点が少ない
  • あなたが本当に怠け者だと感じているならsuccess、コールバックのメソッドは単純にreload保存できます。

議論を促すために、この回答を少し置いておきます。

読んでくれてありがとう!

于 2013-07-24T12:41:35.873 に答える