ExtJS和复合保存操作

时间:2013-05-14 20:04:48

标签: javascript model-view-controller extjs orm extjs4

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的帖子很少得到讨论。我决定将大部分复杂的保存操作加载到我的应用程序服务器上,并在需要时懒洋洋地刷新客户端存储。这样我就可以使用自己的数据库包装器来包含与一个复杂域对象保存相关的所有事务,以保证原子性。如果保存新的Order包括保存订单元数据,10个OrderContents的新实例以及可能的其他信息(驻留在其他表中的地址,订单创建时定义的新客户等)我宁愿将有效负载发送到应用服务器,而不是在客户端应用程序代码中建立一个粗俗的回调网络。在Order操作的Address回调中更新了一对一关联的数据(例如success hasOne Order.save())。只需调用Order即可轻松处理更复杂的数据,例如contentStore.sync()的内容。 我认为这是保证原子性的手段而没有大量的客户回调

原始帖子内容

鉴于保存关联模型的整体令人失望的功能,我在应用程序中除了抛弃模型关联外,还依赖于自己检索相关数据。这一切都很好,但遗憾的是无法解决实际保存数据和更新ExtJS存储以反映服务器上的更改的问题。

例如保存一个Order对象,该对象由元数据和OrderContents组成,即订单中的部分。元数据最终位于数据库中的Order_Data表中,而内容全部以Order_Contents表结尾,其中每一行都通过order_id列链接到父订单。

在客户端上,检索订单的内容非常容易,无需任何关联:var contents = this.getContentsStore().query('order_id', 10).getRange()。但是,一个主要的缺陷是这是在OrderContents ExtJS商店中可用的内容记录,如果我使用的数据服务器没有返回的关联,那么这将适用于主要的“对象。

保存订单时,我发送一个包含订单元数据的请求(例如,日期,订单号,供应商信息等)以及一系列内容。这些数据被挑选出来并保存到适当的表中。这对我来说足够有意义并且运作良好。

一切顺利,直到从应用程序服务器返回保存/更新的记录。由于通过调用OrderObject.save()来触发请求,因此OrderContents商店无法告知新记录可用。如果我要将记录添加到商店并调用.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()

的情况下不应将记录传递给应用程序服务器

这种做法对我来说似乎有点草率/骇客,但我还没有想出更好的解决方案......

非常感谢任何意见/想法!

1 个答案:

答案 0 :(得分:3)

更新8/26/13 我发现相关数据确实是由模型代理上的创建/更新回调中的Ext处理的,但是发现数据并不容易...查看我的在这里发帖:ExtJS 4.1 - Returning Associated Data in Model.Save() Response

嗯,这个问题已经开了几个月了,我觉得这个问题没有神奇的解决方案。

我的解决方案如下......

当保存复杂模型(例如,将会或者确实具有少量hasMany关联的模型)时,我保存包含所有相关数据的“父”模型(作为模型上的属性/字段) !)然后在afterSave / afterUpdate回调中添加(保存的)相关数据。

以我的PurchaseOrder模型为例hasMany 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

我为ModelsPurchaseOrder.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()回调的混乱字符串
  • 只有一个非常容易管理的请求
  • 在应用程序服务器上轻松处理原子性
  • 减少往返次数=减少潜在的失败点
  • 如果你真的感到懒惰,回调的success方法只能reload存储。

我会让这个答案有点鼓励讨论。

感谢阅读!